OPC-UA server

OPC-UA server

When someone told me to use one of the already existing OPC-UA servers and implement them so that the data gets directly sent into the cloud, I thought it sounded easy. Just configure them and boom, that should be it, right?

Well, there is not one single version out there that supports something like that. Why? The software is old, built on outdated standards dating back to the 90s. That's not necessarily bad, but it becomes problematic when there are no further improvements.

So, how do we achieve something like that today? With Windows clients that look and feel like they're straight from the 90s. At this point, do you really need to look into the code of the servers? Well, I don't.

Luckily, there is open-source software available, like Rust Crates or even Python alternatives, where you can see the code. These tools are developed by a small team of unpaid developers. Now, you might think they must be inferior and not provide meaningful usage, right? Well, buckle your seatbelt because they don't. Surprisingly, they are rather performant and easily customizable. And did I mention they are free?

So, does it mean I need a lot of time to do all this right? Well... the last time I did it, it took me just 4 hours to make it work, from variable to MQTT topic.

Code

Below you can see a short code snippet

 
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
 
 
 
    try:
        import json
        import asyncio
        from datetime import timezone
        import datetime
    except (ImportError, ModuleNotFoundError) as exception:
        raise exception
 
 
    class Event:
 
        def __init__(self, sync_rate_publish, sync_rate_subscribe):
            self.sync_rate_publish = int(sync_rate_publish)
            self.sync_rate_subscribe = int(sync_rate_subscribe)
 
        async def publish(self, objs):
            await asyncio.sleep(self.sync_rate_publish)
 
            batch = []
            for obj in objs:
                data = await self._publish(obj)
                if data.get("variables") is not None:
                    if len(data.get("variables")) != 0:
                        batch.append(data)
 
            if len(batch) != 0:
                return batch
            else:
                return "N.a."
 
        async def subscribe(self, data):
            await asyncio.sleep(self.sync_rate_subscribe)
            data = json.dumps(data.decode())
            data = data.replace("\'", '\"')
            data = data[1:]
            data = data[:-1]
            data_dict = json.loads(data)
            return data_dict['data']
 
        async def _publish(self, obj):
            async def get_browse_name(obj, standard):
                try:
                    return (await obj.read_browse_name()).Name
 
                except (Exception,):
                    return standard
 
            async def get_value(obj, standard):
                try:
                    data = []
                    variables = await obj.get_variables()
                    if len(variables) is not 0:
                        [data.append({str((await var.read_browse_name()).Name): await var.read_value()})
                         for var in variables if str((await var.read_browse_name()).Name) != "ServerStatus"]
                        return data
                    else:
                        return None
 
                except (Exception,):
                    return standard
 
            self.data = {
                "timestamp[utc]": self.__synchronous_utility_method(
                    function=lambda: datetime.datetime.now(timezone.utc).replace(tzinfo=timezone.utc).timestamp(),
                    standard="N.a."),
                "object": await get_browse_name(obj=obj, standard="N.a."),
                "variables": await get_value(obj=obj, standard="N.a.")
            }
 
            return self.data
 
        @staticmethod
        def __synchronous_utility_method(function, standard):
            try:
                return function()
            except (Exception,):
                return standard

Sounds interesting?

Get in touch with me and I will help you transform your IT & OT landscape, far more cost-effectively and efficiently than these servers ever could. Oh, and did I mention it's even safer? Well, it is.

Get in touch with me via


August 10, 2023
finished
OPC-UA server, open-source software, Rust Crates, Python, performance, customization, cost-effective