Skip to content

Commit

Permalink
Merge pull request #40 from RaaLabs/add-opcua-server
Browse files Browse the repository at this point in the history
Add opcua server
  • Loading branch information
katarinagud authored Oct 29, 2024
2 parents 7765c87 + 8d39430 commit 7e29071
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
push:
branches:
- '**'
paths-ignore:
- 'MockServer/**'
pull_request:
types: [ closed ]

Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/release-server.yml
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 }}"
7 changes: 7 additions & 0 deletions MockServer/Dockerfile.Client
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" ]
9 changes: 9 additions & 0 deletions MockServer/Dockerfile.Server
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" ]
25 changes: 25 additions & 0 deletions MockServer/README.md
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
}
]
}
````
34 changes: 34 additions & 0 deletions MockServer/client.py
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())
1 change: 1 addition & 0 deletions MockServer/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
asyncua==1.1.5
48 changes: 48 additions & 0 deletions MockServer/server.py
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)

0 comments on commit 7e29071

Please sign in to comment.