-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from RaaLabs/add-opcua-server
Add opcua server
- Loading branch information
Showing
8 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ on: | |
push: | ||
branches: | ||
- '**' | ||
paths-ignore: | ||
- 'MockServer/**' | ||
pull_request: | ||
types: [ closed ] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
name: Release opcua server | ||
|
||
on: | ||
push: | ||
branches: | ||
- '**' | ||
paths: | ||
- 'MockServer/**' | ||
|
||
env: | ||
IMAGES: raaedge.azurecr.io/opcua-test-server | ||
COVERAGE_FOLDER: Coverage | ||
|
||
jobs: | ||
ci: | ||
name: 'Release OPCUA server' | ||
runs-on: ubuntu-latest | ||
env: | ||
RELEASE: ${{ github.event_name == 'push' && contains('main,master', github.ref_name) }} | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: docker/setup-qemu-action@v3 | ||
- uses: docker/setup-buildx-action@v3 | ||
|
||
- uses: mathieudutour/[email protected] | ||
name: Calculate next version and create tag on GitHub | ||
id: tag | ||
with: | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
tag_prefix: ${{ inputs.component && format('server/v',inputs.component) || 'server/v' }} | ||
fetch_all_tags: true | ||
dry_run: ${{ env.RELEASE != 'true' }} | ||
release_branches: ${{ inputs.branches }} | ||
|
||
- name: Apply version tag to Docker images | ||
id: references | ||
run: | | ||
echo ${{ github.event_name }} | ||
IMAGES=$(tr "," "\n" <<<"${{ env.IMAGES }}" | sed "s/^[[:space:]]*//;s/[[:space:]]*$//") | ||
echo -e "Images to tag:\n$IMAGES" | ||
REFS=$(sed "s/$/:v${{ steps.tag.outputs.new_version }}/" <<<"$IMAGES" | paste -sd "," -) | ||
echo -e "References: $REFS" | ||
echo "tags=$REFS" >> $GITHUB_OUTPUT | ||
- name: 'ACR login' | ||
uses: azure/docker-login@v2 | ||
with: | ||
login-server: ${{ secrets.RAAEDGE_LOGIN_SERVER }} | ||
username: ${{ secrets.RAAEDGE_ACR_USERNAME }} | ||
password: ${{ secrets.RAAEDGE_ACR_PASSWORD }} | ||
|
||
- name: Docker push | ||
uses: docker/build-push-action@v6 | ||
if: ${{ env.RELEASE == 'true' }} | ||
with: | ||
push: true | ||
context: . | ||
file: 'MockServer/Dockerfile.Server' | ||
secrets: | | ||
NUGET_GITHUB_PACKAGES_USERNAME=${{ secrets.NUGET_GITHUB_PACKAGES_USERNAME }} | ||
NUGET_GITHUB_PACKAGES_TOKEN=${{ secrets.NUGET_GITHUB_PACKAGES_TOKEN }} | ||
platforms: linux/amd64 | ||
tags: ${{ steps.references.outputs.tags }} | ||
build-args: | | ||
BUILD_VERSION=${{ steps.tag.outputs.new_version }} | ||
- name: Docker logout | ||
if: always() | ||
run: | | ||
docker logout ${{ secrets.RAAEDGE_LOGIN_SERVER }} | ||
docker logout ${{ secrets.RAAEDGE_LOGIN_SERVER_2 }} | ||
- name: Create GitHub Release | ||
if: ${{ env.RELEASE == 'true' }} | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: | | ||
gh release create ${{ steps.tag.outputs.new_tag }} --target=${{ github.sha }} --title="server/v${{ steps.tag.outputs.new_version }}" --notes="${{ steps.tag.outputs.changelog }}" | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM python:3.12.0-slim | ||
|
||
COPY client.py . | ||
|
||
RUN pip install asyncua | ||
|
||
CMD [ "python", "./client.py" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM python:3.12.0-slim | ||
|
||
COPY server.py . | ||
|
||
RUN pip install asyncua | ||
|
||
EXPOSE 4840 | ||
|
||
CMD [ "python", "./server.py" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# opcua-test-server | ||
|
||
````bash | ||
docker build -f Dockerfile.Server -t opcua-test-server . | ||
docker build -f Dockerfile.Client -t opcue-test-client . | ||
|
||
docker network create my-net | ||
docker run --name opcuaserver --network my-net -p 4840:4840 docker.io/library/opcua-test-server | ||
docker run --network my-net docker.io/library/opcua-test-client | ||
```` | ||
|
||
Config for OPCUA connector: | ||
````json | ||
{ | ||
"serverUrl": "opc.tcp://opcua-test-server:4840/freeopcua/server/", | ||
"publishingIntervalSeconds": 1.0, | ||
"nodes": [ | ||
{ | ||
"nodeId": "ns=2;i=2", | ||
"subscribeIntervalSeconds": 1.0, | ||
"readIntervalSeconds": 10.0 | ||
} | ||
] | ||
} | ||
```` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import asyncio | ||
|
||
from asyncua import Client | ||
|
||
url = "opc.tcp://opcuaserver:4840/freeopcua/server/" | ||
namespace = "http://examples.freeopcua.github.io" | ||
|
||
|
||
async def main(): | ||
|
||
print(f"Connecting to {url} ...") | ||
async with Client(url=url) as client: | ||
# Find the namespace index | ||
nsidx = await client.get_namespace_index(namespace) | ||
print(f"Namespace Index for '{namespace}': {nsidx}") | ||
|
||
# Get the variable node for read / write | ||
var = await client.nodes.root.get_child( | ||
f"0:Objects/{nsidx}:MyObject/{nsidx}:MyVariable" | ||
) | ||
value = await var.read_value() | ||
print(f"Value of MyVariable ({var}): {value}") | ||
|
||
new_value = value - 50 | ||
print(f"Setting value of MyVariable to {new_value} ...") | ||
await var.write_value(new_value) | ||
|
||
# Calling a method | ||
res = await client.nodes.objects.call_method(f"{nsidx}:ServerMethod", 5) | ||
print(f"Calling ServerMethod returned {res}") | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
asyncua==1.1.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import asyncio | ||
import logging | ||
import os | ||
|
||
from asyncua import Server, ua | ||
from asyncua.common.methods import uamethod | ||
|
||
|
||
@uamethod | ||
def func(parent, value): | ||
return value * 2 | ||
|
||
|
||
async def main(): | ||
_logger = logging.getLogger(__name__) | ||
server = Server() | ||
await server.init() | ||
|
||
endpoint = os.environ.get("ENDPOINT_URI", "opc.tcp://0.0.0.0:4840/freeopcua/server/") | ||
interval_seconds = int(os.environ.get("PUBLISH_INTERVAL_SECONDS", 1)) | ||
|
||
server.set_endpoint(endpoint) | ||
|
||
uri = "http://examples.freeopcua.github.io" | ||
idx = await server.register_namespace(uri) | ||
|
||
myobj = await server.nodes.objects.add_object(idx, "MyObject") | ||
myvar = await myobj.add_variable(idx, "MyVariable", 6.7) | ||
await myvar.set_writable() | ||
await server.nodes.objects.add_method( | ||
ua.NodeId("ServerMethod", idx), | ||
ua.QualifiedName("ServerMethod", idx), | ||
func, | ||
[ua.VariantType.Int64], | ||
[ua.VariantType.Int64], | ||
) | ||
_logger.info("Starting server!") | ||
async with server: | ||
while True: | ||
new_val = await myvar.get_value() + 0.1 | ||
_logger.info("Set value of %s to %.1f", myvar, new_val) | ||
await myvar.write_value(new_val) | ||
await asyncio.sleep(interval_seconds) | ||
|
||
|
||
if __name__ == "__main__": | ||
logging.basicConfig(level=logging.DEBUG) | ||
asyncio.run(main(), debug=True) |