Example #1
0
def start():
    mServer = Server()
    mServer.set_endpoint(URL)
    mServer.set_security_policy([
        ua.SecurityPolicyType.NoSecurity,
        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
        ua.SecurityPolicyType.Basic256Sha256_Sign
    ])

    address_space = mServer.register_namespace(NAMESPACE_NAME)
    root_node = mServer.get_objects_node()
    params = root_node.add_object(address_space, "Parameters")
    start_time = params.add_variable(address_space, "start_time",
                                     start_timestamp)

    data = root_node.add_object(address_space, "data")

    pump = data.add_object(address_space, "Pump")
    temperature = 20 + random.randint(0, 10)
    pump_temp_var = pump.add_variable(address_space, "temperature",
                                      temperature)
    pump_temp_vup = VarUpdater(
        pump_temp_var)  # just  a dummy class update a variable

    pump_temp_unit = pump.add_variable(address_space, "unit", "°C")
    pump_status = pump.add_variable(address_space, "status", False)
    pump_status.set_writable()
    level = 12
    pump_level = pump.add_variable(address_space, "level", level)
    pump_level.set_writable()

    sleep_period = 0.5
    # Start the server
    mServer.start()
    print("Server started at {}".format(URL))

    print("root_node: " + root_node.__str__())
    print("params: " + params.__str__())
    print("pump: " + pump.__str__())
    # print(""+pump)

    # enable following if you want to subscribe to nodes on server side
    handler = SubHandler()
    sub = mServer.create_subscription(500, handler)
    handle = sub.subscribe_data_change(pump_level)

    # IMPORTANT: This should be started after the mServer.start()
    pump_temp_vup.start()
    try:
        while True:
            time.sleep(sleep_period)
    finally:
        # close connection, remove subscriptions, etc
        pump_temp_vup.stop()  # should be stopped
        mServer.stop()
Example #2
0
def main():
    # logging.basicConfig(level=logging.ERROR)
    # logger=logging.getLogger("opcua.server.internal_subscription")
    # logger.setLevel(logging.ERROR)
    read = open('config.txt', 'r')
    configs = read.readlines()
    read.close()

    server = Server()
    endpoint = configs[0].split('@')[1].rstrip('\n')
    servername = configs[1].split('@')[1].rstrip('\n')
    kafkaservers = configs[2].split('@')[1].replace("'", "").replace(
        "\"", "").rstrip('\n')
    kafkaserver = kafkaservers[1:-1].split(',')
    kafkatopic = configs[3].split('@')[1].rstrip('\n')
    eventname = configs[4].split('@')[1].rstrip('\n')
    # auto_offset_reset='earlist'
    consumer = KafkaConsumer(kafkatopic, bootstrap_servers=kafkaserver)

    server.set_endpoint(endpoint)
    server.set_server_name(servername)

    print("Program running......")
    print("Please do not close this page")

    # 证书
    # server.load_certificate("certificate-example.der")
    # server.load_private_key("private-key-example.pem")
    # 安全策略
    server.set_security_policy([
        ua.SecurityPolicyType.NoSecurity,
        # ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
        # ua.SecurityPolicyType.Basic256Sha256_Sign
    ])

    uri = "http://taiji.com.cn"
    idx = server.register_namespace(uri)

    objs = server.get_objects_node()
    myobj = objs.add_object(idx, "MyObject")
    # 节点
    taglists = readFile("node.csv")
    for taglist in taglists:
        # myobj.add_variable(idx, taglist, 6.7).set_writable()
        myobj.add_variable(idx, taglist, random.random()).set_writable()
        # myobj.add_variable(idx, taglist, 6.7)

    attrs = readFile("ae_attr.csv")
    custom_etype = server.nodes.base_event_type.add_object_type(idx, eventname)
    for attr in attrs:
        custom_etype.add_property(2, attr, ua.Variant("",
                                                      ua.VariantType.String))
    myevent = server.get_event_generator(custom_etype, myobj)

    server.start()

    try:
        rootnode = server.get_root_node().get_child(
            ["0:Objects", "{}:MyObject".format(idx)])
        rootnodes = rootnode.get_variables()

        nodeAll = {}
        for i in range(len(rootnodes)):
            nodeId = rootnodes[i]
            nodeName = rootnodes[i].get_browse_name().Name
            nodeAll.update({nodeName: nodeId})

        for message in consumer:
            recv = message.value.decode("utf8")
            # print("recvevent=",recv)

            if recv[0] == '{' and recv[-1] == '}':
                nodeKafka = json.loads(recv)
                # print("nodeKafka=", nodeKafka)
                comName = nodeKafka.keys() & nodeAll.keys()
                for row in comName:
                    rootnode.get_child(["2:{}".format(row)
                                        ]).set_value(nodeKafka[row])
            else:
                recv = recv.replace('\n', '').replace('\r', '')
                datas = recv.split("|")[1:]
                # print("datas=", datas)
                if len(datas) == 9:
                    for i in range(len(attrs)):
                        # exec("myevent.event.{}='{}'".format(attrs[i], datas[i].replace('\n', '').replace('\r', '')))
                        exec("myevent.event.{}='{}'".format(
                            attrs[i], datas[i]))
                    myevent.trigger()
                else:
                    # continue
                    f = open('ErrorAE.bak', 'a', encoding='utf8')
                    f.write(recv)
                    f.write('\n')
                    f.close
                # print("mysecondevgen=",mysecondevgen)
                # print("mysecondevgen=", myevent.event)

    except Exception as e:
        print(e)

    finally:
        server.stop()
Example #3
0
        print("device has been stopped")


if __name__ == "__main__":

    logger = logging.getLogger()
    logger.setLevel(logging.WARNING)
    logging.basicConfig(stream=sys.stdout)

    server = Server()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")

    # set all possible endpoint policies for clients to connect through
    server.set_security_policy([
        ua.SecurityPolicyType.Basic256Sha256_Sign,
        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
    ])

    server.load_certificate("cert.pem")
    server.load_private_key("key.pem")

    server.user_manager.user_manager = lambda session, username, password: username == "testuser" and password == "testpass2"

    # setup our own namespace
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # direct directly some objects and variables
    device = server.nodes.objects.add_object(idx, "device")

    device_switch = device.add_variable(idx, "switch", True)
                ua.Variant(db_value, ua.VariantType.UInt64)     #Value from database
            )  
            
if __name__ == "__main__":
    """
    OPC-UA-Server Setup
    """
    server = Server()
    server.set_endpoint("opc.tcp://127.0.0.1:4840")
    server.set_server_name("PythonOpcUaServer")
    security_policy =   [
                            ua.SecurityPolicyType.NoSecurity,
                            #ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
                            #ua.SecurityPolicyType.Basic256Sha256_Sign
                        ]
    server.set_security_policy(security_policy)
    policyIDs =   [
                    "Anonymous", "Basic256Sha256", "Username"
                ]
    server.set_security_IDs(policyIDs)
    address_space = server.register_namespace("http://andreas-heine.net/UA")

    """
    OPC-UA-Modeling
    """
    root_node = server.get_root_node()
    object_node = server.get_objects_node()
    server_node = server.get_server_node()

    #S7-1500 Checks frequently the service level so make sure it has a value (http://documentation.unified-automation.com/uasdkcpp/1.5.3/html/L2ServerRedundancy.html)
    servicelevel_node = server.get_node("ns=0;i=2267") #Service-Level Node
Example #5
0
class StationUAServer:
    def __init__(self, pick_by_light):
        self._pbl = pick_by_light
        self._setup_nodes()
        self._generate_tags()

        self.ua_server.start()

        self._generate_subscriptions()
        Thread(target=self._var_updater, daemon=True).start()

    def _setup_nodes(self):

        # Create server instance
        self.ua_server = Server('./opcua_cache')
        self.ua_server.set_endpoint('opc.tcp://0.0.0.0:4840/UA/PickByLight')
        self.ua_server.set_server_name("Pick By Light Server")
        # idx name will be used later for creating the xml used in data type dictionary
        # setup our own namespace, not really necessary but should as spec
        idx_name = 'http://examples.freeopcua.github.io'
        self.idx = self.ua_server.register_namespace(idx_name)

        # Set all possible endpoint policies for clients to connect through
        self.ua_server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt,
            ua.SecurityPolicyType.Basic128Rsa15_Sign,
            ua.SecurityPolicyType.Basic256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256_Sign
        ])

        # get Objects node, this is where we should put our custom stuff
        objects = self.ua_server.get_objects_node()

        # Create objects for the pack tags using the above created packMLBasedObjectType
        self.Status = objects.add_folder('ns=2;s=Status', "Status")
        self.Command = objects.add_folder('ns=2;s=Command', "Command")
        self.Command.add_method('ns=2;s=Command.SelectPort', "SelectPort",
                                self._select_method,
                                [ua.VariantType.Int32, ua.VariantType.String],
                                [ua.VariantType.Boolean])
        self.Command.add_method('ns=2;s=Command.DeselectPort', "DeselectPort",
                                self._deselect_method, [ua.VariantType.Int32],
                                [ua.VariantType.Boolean])
        self.Command.add_method('ns=2;s=Command.DeselectAllPorts',
                                "DeselectAllPorts", self._deselect_all_method,
                                [], [ua.VariantType.Boolean])

        root = self.ua_server.get_root_node()
        DummyFestoObj = root.add_object(
            "ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables",
            "DummyFesto")
        DummyFestoObj.add_variable(
            "ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables.FlexStationStatus",
            "FlexStationStatus",
            val=0).set_writable()
        DummyFestoObj.add_variable(
            "ns=2;s=|var|CECC-LK.Application.FBs.stpStopper1.stAppControl.uiOpNo",
            "uiOpNo",
            val=0).set_writable()
        DummyFestoObj.add_variable(
            "ns=2;s=ns=2;s=|var|CECC-LK.Application.AppModul.stRcvData.sOderDes",
            "sOderDes",
            val="").set_writable()

    def _generate_tags(self):
        # for all ports generate tags
        for port_number, port in self._pbl.get_ports():
            # Make a folder with the port_number as the name
            b_obj = self.Status.add_object(
                'ns=2;s=Status.Port_{}'.format(port_number),
                "Port_{}".format(port_number))

            content = self._pbl.get_content(port_number)

            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.Selected".format(port_number),
                "Selected", bool())
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.WorkFinished".format(port_number),
                "WorkFinished", bool())
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.Instructions".format(port_number),
                "Instructions", "")
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.Activity".format(port_number),
                "Activity", bool())
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.ActivityTimestamp".format(port_number),
                "ActivityTimestamp", datetime.fromtimestamp(0))
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.LightState".format(port_number),
                "LightState", 0)
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.ContentDisplayName".format(port_number),
                "ContentDisplayName", content['display_name'])
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.ContentName".format(port_number),
                "ContentName", content['name'])
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.ContentDescription".format(port_number),
                "ContentDescription", content['description'])
            b_obj.add_variable(
                "ns=2;s=Status.Port_{}.ContentImagePath".format(port_number),
                "ContentImagePath", content['image_path'])
            '''
            create command tags for clients that does not support ua methods. 
            '''
            b_obj = self.Command.add_object(
                'ns=2;s=Command.Port_{}'.format(port_number),
                "Port_{}".format(port_number))

            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.Select".format(port_number), "Select",
                bool()).set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.Deselect".format(port_number),
                "Deselect", bool()).set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.Instructions".format(port_number),
                "Instructions", "").set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.ContentDisplayName".format(
                    port_number), "ContentDisplayName",
                content['display_name']).set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.ContentName".format(port_number),
                "ContentName", content['name']).set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.ContentDescription".format(
                    port_number), "ContentDescription",
                content['description']).set_writable()
            b_obj.add_variable(
                "ns=2;s=Command.Port_{}.ContentImagePath".format(port_number),
                "ContentImagePath", content['image_path']).set_writable()
        '''
        Generate some common commands 
        '''
        # Make a folder for the commons
        b_obj = self.Command.add_object('ns=2;s=Command.ByContent',
                                        'ByContent')

        b_obj.add_variable("ns=2;s=Command.ByContent.Select", "Select",
                           bool()).set_writable()
        b_obj.add_variable("ns=2;s=Command.ByContent.Deselect", "Deselect",
                           bool()).set_writable()
        b_obj.add_variable("ns=2;s=Command.ByContent.Name", "Name",
                           "").set_writable()
        b_obj.add_variable("ns=2;s=Command.ByContent.Instructions",
                           "Instructions", "").set_writable()
        b_obj.add_variable("ns=2;s=Command.ByContent.Result", "Result",
                           -1).set_writable()

    def _generate_subscriptions(self):
        # Create UA subscriber node for the box. Set self as handler.
        sub = self.ua_server.create_subscription(100, self)

        # Subscribe to the Select tag and all the content tags
        for port_number, port in self._pbl.get_ports():
            ac = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.Select".format(port_number))
            sub.subscribe_data_change(ac)
            ac = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.Deselect".format(port_number))
            sub.subscribe_data_change(ac)
            b = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.ContentDisplayName".format(
                    port_number))
            sub.subscribe_data_change(b)
            c = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.ContentName".format(port_number))
            sub.subscribe_data_change(c)
            d = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.ContentDescription".format(
                    port_number))
            sub.subscribe_data_change(d)
            e = self.ua_server.get_node(
                "ns=2;s=Command.Port_{}.ContentImagePath".format(port_number))
            sub.subscribe_data_change(e)
            a = self.ua_server.get_node("ns=2;s=Command.ByContent.Select")
            sub.subscribe_data_change(a)
            a = self.ua_server.get_node("ns=2;s=Command.ByContent.Deselect")
            sub.subscribe_data_change(a)
            a = self.ua_server.get_node("ns=2;s=Command.ByContent.Name")
            sub.subscribe_data_change(a)
            a = self.ua_server.get_node(
                "ns=2;s=Command.ByContent.Instructions")
            sub.subscribe_data_change(a)

    def _event_notification(self, event):
        logger.warning(
            "Python: New event. No function implemented. {}".format(event))

    def _select_method(self, parrent, port_number, instructions):
        r = self._pbl.select_port(port_number.Value,
                                  instructions=instructions.Value)
        return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)]

    def _deselect_method(self, parrent, port_number):
        r = self._pbl.deselect_port(port_number.Value)
        return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)]

    def _deselect_all_method(self, parrent):
        r = self._pbl.deselect_all()
        return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)]

    def datachange_notification(self, node, val, data):
        """UA server callback on data change notifications        
        Arguments:
            node {Node} -- [description]
            val {[type]} -- [description]
            data {[type]} -- [description]
        """

        logger.debug("New data change event. node:{}, value:{}".format(
            node, val))

        # Sorry about these lines of code, but I don't see any nicer way of determining the port number than from
        # the identifier string. Then splitting it up to isolate the port number.
        # Example "Status.Port_2.Selected"  is split into ['Status', 'Port_2', 'Selected'] then 'Port_2' is split into
        # ['Port', '2'] and then the '2' is turned into an intiger.
        path_list = str(node.nodeid.Identifier).split(".")

        # We can safely assume that the last term is the tag that updated.
        tag = path_list[-1]

        # Figure out the port number
        port_number = None
        if 'Port' in path_list[1]:
            port_number = int(path_list[1].split("_")[-1])
        """ Switch for each possible tag"""
        # If the command tag "Select" changes go select that port with the instructions saved in the command tag.
        if tag == 'Select' and port_number:
            if val == True:
                node = self.ua_server.get_node(
                    "ns=2;s=Command.Port_{}.Instructions".format(port_number))
                instructions = node.get_value()
                self._pbl.select_port(port_number, instructions=instructions)
                # Reset the select flag
                node = self.ua_server.get_node(
                    "ns=2;s=Command.Port_{}.Select".format(port_number))
                node.set_value(False)

        elif tag == 'Deselect' and port_number:
            if val == True:
                self._pbl.deselect_port(port_number, work_finished=True)
                # Reset the select flag
                node = self.ua_server.get_node(
                    "ns=2;s=Command.Port_{}.Deselect".format(port_number))
                node.set_value(False)

        elif tag == 'ContentDisplayName' and port_number:
            self._pbl.set_content_key(port_number, 'display_name', str(val))
        elif tag == 'ContentName' and port_number:
            self._pbl.set_content_key(port_number, 'name', str(val))
        elif tag == 'ContentDescription' and port_number:
            self._pbl.set_content_key(port_number, 'description', str(val))
        elif tag == 'ContentImagePath' and port_number:
            self._pbl.set_content_key(port_number, 'image_path', str(val))

        elif tag == 'Select' and 'ByContent' in path_list[1]:
            if val == True:
                instructions = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Instructions").get_value()
                name = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Name").get_value()
                _, selected_port = self._pbl.select_content(
                    name=name, instructions=instructions)
                # Reset the select flag
                node = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Select")
                node.set_value(False)
                node = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Result")
                node.set_value(selected_port)

        elif tag == 'Deselect' and 'ByContent' in path_list[1]:
            if val == True:
                name = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Name").get_value()
                self._pbl.deselect_content(name=name, work_finished=True)
                # Reset the select flag
                node = self.ua_server.get_node(
                    "ns=2;s=Command.ByContent.Deselect")
                node.set_value(False)

    def _var_updater(self):
        while True:
            sleep(0.1)
            # for all boxes update tags
            for port_number, port in self._pbl.get_ports():
                # get the object in the packml status object using our unique idx
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.Activity".format(port_number))
                node.set_value(port.activity)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.ActivityTimestamp".format(
                        port_number))
                node.set_value(port.activity_timestamp)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.LightState".format(port_number))
                node.set_value(port.get_light())

                state = self._pbl.get_port_state(port_number)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.Selected".format(port_number))
                node.set_value(state.selected)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.WorkFinished".format(port_number))
                node.set_value(state.work_finished)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.Instructions".format(port_number))
                node.set_value(state.select_instructions)

                content = self._pbl.get_content(port_number)
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.ContentDisplayName".format(
                        port_number))
                node.set_value(content['display_name'])
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.ContentName".format(port_number))
                node.set_value(content['name'])
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.ContentDescription".format(
                        port_number))
                node.set_value(content['description'])
                node = self.ua_server.get_node(
                    "ns=2;s=Status.Port_{}.ContentImagePath".format(
                        port_number))
                node.set_value(content['image_path'])
Example #6
0
    def __init__(self, name, shared):
        super().__init__(name, shared)
        self.logger = logging.getLogger(self.name)
        self.logger.info("init")

        self.shared.config.set_hidden_value(self.name, "user")
        self.shared.config.set_hidden_value(self.name, "password")
        self.shared.config.set_hidden_value(self.name, "password_hash")

        def config(key, val):
            return self.shared.config.config(self.name, key, val)

        endpoint = config("endpoint", "no_endpoint")
        certificate = config("certificate", "")
        private_key = config("private_key", "")
        uri = config("uri", "http://examples.freeopcua.github.io")
        root_object_name = config("root_object_name", "TEST")
        separator = config("separator", ".")
        namespace = config("namespace", 2)

        self.oldnew = config("oldnew_comparision", 0)

        admin_username = config("user", "admin")
        admin_password = config("password", "admin")
        admin_password_hash = config("password_hash", "").replace("$$", "$")

        security_ids = []
        anonymous_on = config("anonymous_on", 0)
        username_on = config("username_on", 1)
        certificate_on = config("certificate_basic256sha256_on", 0)

        if anonymous_on:
            security_ids.append("Anonymous")
        if username_on:
            security_ids.append("Username")
        if certificate_on:
            security_ids.append("Basic256Sha256")

        security_policy = []

        if config("nosecurity_on", 1):
            security_policy.append(ua.SecurityPolicyType.NoSecurity)
        if config("basic128rsa15_sign_on", 0):
            security_policy.append(ua.SecurityPolicyType.Basic128Rsa15_Sign)
        if config("basic128rsa15_signandencrypt_on", 0):
            security_policy.append(
                ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt)
        if config("basic256_sign_on", 0):
            security_policy.append(ua.SecurityPolicyType.Basic256_Sign)
        if config("basic256_signandencrypt_on", 0):
            security_policy.append(
                ua.SecurityPolicyType.Basic256_SignAndEncrypt)
        if config("basic256sha256_sign_on", 1):
            security_policy.append(ua.SecurityPolicyType.Basic256Sha256_Sign)
        if config("basic256sha256_signandencrypt_on", 1):
            security_policy.append(
                ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt)

        initial_values_is_quality_good = config(
            "initial_values_is_quality_good", 0)

        if anonymous_on:
            server = Server()
        else:
            server = Server(iserver=CustomInternalServer())
            server.iserver.set_parent(server)

        server.set_endpoint(endpoint)
        server.allow_remote_admin(False)

        if certificate and private_key:
            server.load_certificate(str(certificate))
            server.load_private_key(str(private_key))

        if security_ids:
            server.set_security_IDs(security_ids)

        if security_policy:
            server.set_security_policy(security_policy)

        def custom_user_manager(isession, userName, password):
            if userName != admin_username:
                return False
            if admin_password_hash:
                if werkzeug.security.check_password_hash(
                        admin_password_hash, password):
                    return True
            else:
                # fallback to plaintext
                if password == admin_password:
                    return True
            return False

        if username_on:
            server.user_manager.set_user_manager(custom_user_manager)

        idx = server.register_namespace(uri)
        objects = server.get_objects_node()
        root = objects.add_object(idx, root_object_name)

        self.server = server
        self.objects = objects
        self.root = root
        self.sep = separator
        self.ns = namespace
        self.items = []

        if initial_values_is_quality_good:
            self.initial_status_code = ua.StatusCodes.Good
        else:
            self.initial_status_code = ua.StatusCodes.BadWaitingForInitialData
Example #7
0
    #logger = logging.getLogger("opcua.internal_server")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("opcua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("opcua.uaprocessor")
    # logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    #server.disable_clock()
    #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")
    # set possible endpoint policies for clients to connect through
    server.set_security_policy([
        "None", "Basic128Rsa15_Sign", "Basic128Rsa15_SignAndEncrypt",
        "Basic256_Sign", "Basic256_SignAndEncrypt"
    ])

    # setup our own namespace
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # create a new node type we can instantiate in our address space
    dev = server.nodes.base_object_type.add_object_type(0, "MyDevice")
    dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True)
    dev.add_property(0, "device_id", "0340").set_modelling_rule(True)
    ctrl = dev.add_object(0, "controller")
    ctrl.set_modelling_rule(True)
    ctrl.add_property(0, "state", "Idle").set_modelling_rule(True)

    # populating our address space
class ServerOPC():
    def __init__(self, sensori):
        self.keys=c_gpio.led_dict.keys()
        self.sensori=sensori
        self.__led=c_gpio.led_dict        
        self.init_server()
    
    def init_server(self):
        print("inizio settaggio server")       
        self.server=Server()
        #self.server.set_endpoint("opc.tcp://192.168.1.250:4840")
        self.server.set_endpoint("opc.tcp://0.0.0.0:4840")
        self.server.set_server_name("DomoticProject")
        #carico il certificato e la chiave privata
        global base_path        
        file_path_cert=(base_path / "../config/certificati/my_cert.der").resolve()
        file_path_key=(base_path / "../config/certificati/my_private_key.pem").resolve()        
        self.server.load_certificate(file_path_cert)
        self.server.load_private_key(file_path_key)
        self.server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign
        ])
        
        #setup namespace
        uri="Domotic"
        self.idx=self.server.register_namespace(uri)
        self.objects=self.server.get_objects_node()
        
        #per contenere le info dei sensori
        self.sensors_o=self.objects.add_object(self.idx, "Sensori")
        self.temperatura_s=self.sensors_o.add_variable(self.idx, "Temperatura", 0.00)
        self.counterbagno_s=self.sensors_o.add_variable(self.idx, "Counter Bagno", 0)
        self.countersalotto_s=self.sensors_o.add_variable(self.idx, "Counter Salotto", 0)
        
        #per contenere le info dei led
        self.luci_o=self.objects.add_object(self.idx, "Luci")        
        self.luci_o_dict={}
        for x in self.keys:
            self.luci_o_dict[x]=self.luci_o.add_variable(self.idx, "Luce "+x, False)
            self.luci_o_dict[x].set_writable()
        
        #per contenere i metodi
        self.method_o=self.objects.add_object(self.idx, "Metodi")
        
        inarg=ua.Argument()
        inarg.Name="stanza"
        inarg.DataType=ua.NodeId(ua.ObjectIds.String)
        inarg.ValueRank=-1
        inarg.ArrayDimensions=[]
        inarg.Description=ua.LocalizedText("stanza su cui applicare il metodo ['salotto', 'camera', 'bagno', 'ingresso']")
        
        self.mymethod1=self.method_o.add_method(self.idx, "Accendi luce", self.accendi_luce, [inarg])        
        self.mymethod2=self.method_o.add_method(self.idx, "Spegni luce", self.spegni_luce, [inarg])
        
        print("server settato")
                
    def run(self):
        print("start server")
        self.server.start()
        try:
            while True:                
                val=ua.Variant(self.sensori["temperatura"], ua.VariantType.Float)
                val=ua.DataValue(val)                             
                val.SourceTimestamp=datetime.utcnow()                 
                val.ServerTimestamp=datetime.utcnow()                                                                        
                self.temperatura_s.set_data_value(val)                
                
                val2=ua.Variant(self.sensori["counter_bagno"], ua.VariantType.UInt16)
                val2=ua.DataValue(val2)                             
                val2.SourceTimestamp=datetime.utcnow()                 
                val2.ServerTimestamp=datetime.utcnow() 
                self.counterbagno_s.set_data_value(val2)
                
                val3=ua.Variant(self.sensori["counter_salotto"], ua.VariantType.UInt16)
                val3=ua.DataValue(val3)                             
                val3.SourceTimestamp=datetime.utcnow()                 
                val3.ServerTimestamp=datetime.utcnow() 
                self.countersalotto_s.set_data_value(val3)
                
                for x in self.keys:
                    pin=self.__led[x]
                    status=gpio.input(pin)
                    var=ua.Variant(status, ua.VariantType.Boolean)
                    s=ua.DataValue(var)
                    s.SourceTimestamp=datetime.utcnow()
                    s.ServerTimestamp=datetime.utcnow()
                    self.luci_o_dict[x].set_value(s)
                    
                
                time.sleep(1)
                                     
        finally:
            self.server.stop()

    
    @uamethod
    def accendi_luce(self, parent, stanza):
        pin=self.__led[stanza]        
        if stanza=="salotto":
            s=gpio.input(2)
            gpio.output(2, 1)
            gpio.output(pin, 0)
        else:
            gpio.output(pin, 1) 
                  
    @uamethod
    def spegni_luce(self, parent, stanza):
        pin=self.__led[stanza]
        if stanza=="salotto":
            s=gpio.input(2)
            gpio.output(2, 0)
            gpio.output(pin, 1)
        else:
            gpio.output(pin, 0)
    out_extobj.EURange.High = in_extobj.EURange.High
    out_extobj.Title = in_extobj.Title
    out_extobj.AxisScaleType = in_extobj.AxisScaleType
    out_extobj.AxisSteps = in_extobj.AxisSteps

    axis_info.set_value(out_extobj)  #write values to variable

    ret = (ua.Variant(out_extobj, ua.VariantType.ExtensionObject),
           ua.Variant("test", ua.VariantType.String))

    return ret


server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
server.set_security_policy([ua.SecurityPolicyType.NoSecurity])

obj = server.get_objects_node()
idx = server.register_namespace("http://examples.freeopcua.github.io")

server.load_type_definitions()

inarg_extobj = ua.Argument()
inarg_extobj.Name = "In"
inarg_extobj.DataType = ua.NodeId(12079, 0)
inarg_extobj.ValueRank = -1
inarg_extobj.ArrayDimensions = []
inarg_extobj.Description = ua.LocalizedText("Wanted AxisInformation")

outarg_extobj = ua.Argument()
outarg_extobj.Name = "Out"
Example #10
0
class IbaToUaServer():
    """The Server will discover the iba files and prepare the Opc Server accordingly."""
    def __init__(self):
        """Default constructor. Not magic here since everything is hard coded atm.

        Todo: Use config parser to configure the server a little bit
        """

        # init super class constructors
        super().__init__()

        # list of path to iba files
        self.iba_files = list()

        # dictionary containing the channels of the iba files sorted by sample rate
        self.iba_info = dict()

        # dictionary of loaded iba data sorted by sample rate
        self.iba_data = dict()

        # handle to the actual opc ua server
        self._server = None

        # dictionary of threads for each unique sample rate
        self._value_updater = dict()

    def start(self):
        """The actual run function called by the Thread super class. All the magic happens here.

        1. discover the iba files in the dat sub folder
        2. get channels from the iba files
        3. build the opc ua server
        4. read the data
        5. start the updating of the data

        :return:
        """

        # discover iba files
        print('finding iba files ...')
        self.iba_files = self.discover_iba_files()

        # get channels from first iba file
        print('receiving channel info ...')
        self.iba_info = self.get_file_info(self.iba_files[0])

        # build the opc server
        print('building opc server ...')
        self.init_opc()

        # start the server
        print('starting opc server ...')
        self._server.start()

        # create the value updater
        self._write_values()

    def discover_iba_files(self):
        """Call to get a list of iba files in the dat sub directory.

        :return: list of paths to iba files
        :raises: FileNotFoundError
        """

        # where shall i search for files?
        iba_path = os.path.join(os.getcwd(), 'dat')

        # get the list of iba files
        file_list = getSortedIbaFiles(iba_path, scan_sub_folders=False)

        # check if any files have been found
        if not file_list:
            raise FileNotFoundError('Could not find any files at '
                                    '{}'
                                    '.'.format(file_list))

        # TODO: check if all iba files have the same channel configuration. If not this will create problems!

        return file_list

    def get_file_info(self, iba_file):
        """Returns a dict containing all modules defined in the iba file as well as the dictionary with channels group
        by their sample rate.

        :param iba_file: (madatory, string) path to a iba files
        :return: dict with keys: modules (dict), channel (dict)
        """

        # get the actual info
        channel_info = get_channel_info(iba_file)

        # loop over the file to store the info
        modules = dict()
        channels = dict()
        for name, chan in channel_info.items():
            # ignore text channel
            if chan['type'] == 'text' or '$PDA_Tbase' not in chan.keys():
                continue

            # add fields to the channel dict for later use
            chan['opc_obj'] = None
            chan['opc_value'] = None

            # get module
            full_module = '{0} {1}'.format(chan['module_no'], chan['module'])
            if full_module not in modules.keys():
                modules[full_module] = list()
            modules[full_module].append(chan)

            # sort channel
            cur_tbase = chan['$PDA_Tbase']
            if cur_tbase not in channels.keys():
                channels[cur_tbase] = list()
            channels[cur_tbase].append(chan)

        return {'modules': modules, 'channels': channels}

    def init_opc(self):
        """Initializes the actual OPC Server and creates all folder, nodes, etc.

        :return: None
        """

        self._server = Server()
        self._server.set_endpoint(
            "opc.tcp://localhost:4840/sms-digital/iba-playback/")
        self._server.set_server_name("iba Files Playback OPC UA Server")

        # set all possible endpoint policies for clients to connect through
        self._server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign
        ])

        # setup our own namespace
        uri = "http://iba-playback.sms-digital.io"
        idx = self._server.register_namespace(uri)

        # add modules folder
        modules = self._server.nodes.objects.add_folder(idx, "Modules")
        for module, channel in self.iba_info['modules'].items():
            print('\tModule: {} ...'.format(module))
            # create a new folder for the module
            module_folder = modules.add_folder(idx, module)

            # create a folder for analog and digital signals
            analog_folder = module_folder.add_folder(idx, 'Analog')
            digital_folder = module_folder.add_folder(idx, 'Digital')

            # add the channel
            for chan in channel:
                # create channel
                if chan['type'] == 'analog':
                    opc_channel = analog_folder.add_object(idx, chan['name'])
                    val = 0.0
                else:
                    opc_channel = digital_folder.add_object(idx, chan['name'])
                    val = False

                # define the channel object
                value_var = opc_channel.add_variable(idx, "value", val)
                value_var.set_writable(True)
                for key, val in chan.items():
                    opc_channel.add_variable(idx, key, val).set_writable(False)

                # store the handles to the value variable and the opc_channel in the channel dict
                chan['opc_obj'] = opc_channel
                chan['opc_value'] = value_var

    def _write_values(self):
        """Spawn a thread for each sample rate

        :return:
        """

        for sampleRate, channel in self.iba_info['channels'].items():

            # read the data
            channels = list()
            for chan in channel:
                channels.append(chan['id'])

            # TODO: Deal with multiple files
            data = readIbaFile(self.iba_files[0],
                               channels=channels,
                               names=channels)

            # todo: split large files with many channel with the same samplerate into multiple threads

            # create variable update
            VariableUpdater(server=self._server,
                            channel=channel,
                            period=float(sampleRate),
                            data=data).start()
class CustomServer(object):
    def __init__(self):
        self.SERVER_ENDPOINT = os.environ.get("SERVER_ENDPOINT")
        self.NAMESPACE = os.environ.get("NAMESPACE")
        self.SERVER_NAME = os.environ.get("SERVER_NAME")
        self.ENABLE_CERTIFICATE = bool(
            strtobool(os.environ.get("ENABLE_CERTIFICATE")))

        # setup our server
        self.server = Server()
        self.server.set_endpoint(self.SERVER_ENDPOINT)
        self.server.set_server_name(self.SERVER_NAME)

        # set the security endpoints for identification of clients
        if self.ENABLE_CERTIFICATE:
            # load server certificate and private key. This enables endpoints with signing and encryption.
            self.CERTIFICATE_PATH_SERVER_CERT = os.path.dirname(
                os.getcwd()) + os.environ.get("CERTIFICATE_PATH_SERVER_CERT")
            self.CERTIFICATE_PATH_SERVER_PRIVATE_KEY = os.path.dirname(
                os.getcwd()) + os.environ.get(
                    "CERTIFICATE_PATH_SERVER_PRIVATE_KEY")
            self.server.load_certificate(self.CERTIFICATE_PATH_SERVER_CERT)
            self.server.load_private_key(
                self.CERTIFICATE_PATH_SERVER_PRIVATE_KEY)

            # set all possible endpoint policies for clients to connect through
            self.server.set_security_policy([
                # ua.SecurityPolicyType.NoSecurity,
                ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
                # ua.SecurityPolicyType.Basic256Sha256_Sign,
            ])

            self.server.set_security_IDs(["Username", "Basic256Sha256"])
        else:
            self.server.set_security_policy([ua.SecurityPolicyType.NoSecurity])
            self.server.set_security_IDs(["Anonymous", "Username"])

        # set the user_manager function
        self.server.user_manager.set_user_manager(user_manager)

        # setup our own namespace, not really necessary but should as spec
        uri = self.NAMESPACE
        self.idx = self.server.register_namespace(uri)

        # get important nodes
        self.root = self.server.get_root_node()
        self.obj = self.server.get_objects_node()

        self.init_methods()

    def init_methods(self):
        # method: ADD_OBJECTS_DIR
        inarg1 = ua.Argument()
        inarg1.Name = "objects folder"
        inarg1.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg1.ValueRank = -1
        inarg1.ArrayDimensions = []
        inarg1.Description = ua.LocalizedText("Name the new objects folder")

        method_node = self.obj.add_method(self.idx, "ADD_NEW_OBJECTS_FOLDER",
                                          self.add_objects_subfolder, [inarg1])

        # method: ADD_OPC_TAG
        inarg1 = ua.Argument()
        inarg1.Name = "opctag"
        inarg1.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg1.ValueRank = -1
        inarg1.ArrayDimensions = []
        inarg1.Description = ua.LocalizedText("Name new OPC variable")

        inarg2 = ua.Argument()
        inarg2.Name = "variant_type"
        inarg2.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg2.ValueRank = -1
        inarg2.ArrayDimensions = []
        inarg2.Description = ua.LocalizedText("Type of variable")

        inarg3 = ua.Argument()
        inarg3.Name = "parent_node"
        inarg3.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg3.ValueRank = -1
        inarg3.ArrayDimensions = []
        inarg3.Description = ua.LocalizedText(
            "Type in the name of the parent node the new variable should assigned to"
        )

        method_node = self.obj.add_method(self.idx, "ADD_OPC_TAG",
                                          self.register_opc_tag,
                                          [inarg1, inarg2, inarg3])

        # method: SET_PV_LIMIT
        inarg1 = ua.Argument()
        inarg1.Name = "active_power_setpoint"
        inarg1.DataType = ua.NodeId(ua.ObjectIds.Int32)  # Integer
        inarg1.ValueRank = -1
        inarg1.ArrayDimensions = []
        inarg1.Description = ua.LocalizedText(
            "Type in active power setpoint in percent [0 ... 100]")

        inarg2 = ua.Argument()
        inarg2.Name = "parent_node"
        inarg2.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg2.ValueRank = -1
        inarg2.ArrayDimensions = []
        inarg2.Description = ua.LocalizedText(
            "Type in the name of the parent node")

        method_node = self.obj.add_method(self.idx, "SET_PV_LIMIT",
                                          self.set_pv_active_power_setpoint,
                                          [inarg1, inarg2])

        # method: RUN_ONLINE_GRID_PROTECTION
        inarg1 = ua.Argument()
        inarg1.Name = "On/Off"
        inarg1.DataType = ua.NodeId(ua.ObjectIds.Int32)  # Integer
        inarg1.ValueRank = -1
        inarg1.ArrayDimensions = []
        inarg1.Description = ua.LocalizedText(
            "Type in 1 to RUN or 0 to STOP ONLINE_GRID_PROTECTION")

        inarg2 = ua.Argument()
        inarg2.Name = "parent_node"
        inarg2.DataType = ua.NodeId(ua.ObjectIds.String)  # String
        inarg2.ValueRank = -1
        inarg2.ArrayDimensions = []
        inarg2.Description = ua.LocalizedText(
            "Type in the name of the parent node")

        method_node = self.obj.add_method(self.idx,
                                          "RUN_ONLINE_GRID_PROTECTION",
                                          self.run_online_grid_protection,
                                          [inarg1, inarg2])

    @uamethod
    def add_objects_subfolder(self, parent, dir_name):
        # check if old dir with dir_name exists. if so then delete this dir first
        try:
            obj = self.root.get_child(
                ["0:Objects", ("{}:" + dir_name).format(self.idx)])
            self.server.delete_nodes([obj], True)
        except BadNoMatch:
            print(DateHelper.get_local_datetime(),
                  "There is no old folder with the name: " + dir_name)

        folder = self.obj.add_folder(self.idx, dir_name)
        print(DateHelper.get_local_datetime(), "Add subfolder: " + dir_name)

    @uamethod
    def register_opc_tag(self,
                         parent,
                         opctag,
                         variant_type="Float",
                         parent_node=""):
        # Object "parent_node":
        try:
            obj = self.root.get_child(
                ["0:Objects", ("{}:" + parent_node).format(self.idx)])
        except BadNoMatch:
            print(
                DateHelper.get_local_datetime(),
                "register_opc_tag(): OPCUA_server_dir the variables should be assigned to, doesn't exists."
            )
            raise

        var = ua.Variant(0, strings_to_vartyps(variant_type))
        mvar = obj.add_variable(self.idx, opctag.strip(), var)
        mvar.set_writable()
        print(
            DateHelper.get_local_datetime(), "Add variable: " + opctag +
            " of type " + variant_type + " @node " + parent_node)

    @uamethod
    def set_pv_active_power_setpoint(self, parent, setpoint, parent_node=""):
        try:
            obj = self.root.get_child(
                ["0:Objects", ("{}:" + parent_node).format(self.idx)])
        except BadNoMatch:
            print(
                DateHelper.get_local_datetime(),
                "set_pv_active_power_setpoint(): assign new value to node failed."
            )
            raise

        for mvar in obj.get_variables():
            if "PV" and "CTRL" in mvar.get_browse_name().Name:
                variant_type = mvar.get_data_value().Value.VariantType
                mvar.set_value(clamp(setpoint, 0, 100), variant_type)
                print(
                    DateHelper.get_local_datetime(),
                    "Set Value of node " + mvar.get_browse_name().Name +
                    " to " + str(clamp(setpoint, 0, 100)))

    @uamethod
    def run_online_grid_protection(self, parent, setpoint, parent_node=""):
        try:
            obj = self.root.get_child(
                ["0:Objects", ("{}:" + parent_node).format(self.idx)])
        except BadNoMatch:
            print(DateHelper.get_local_datetime(),
                  "run_online_grid_protection(): Change in On/Off failed.")
            raise

        for mvar in obj.get_variables():
            if "RUN_ONLINE_GRID_PROTECTION" in mvar.get_browse_name().Name:
                variant_type = mvar.get_data_value().Value.VariantType
                mvar.set_value(clamp(setpoint, 0, 1), variant_type)
                print(
                    DateHelper.get_local_datetime(),
                    "Change status of online grid protection to " +
                    str(clamp(setpoint, 0, 1)))

    def start(self):
        self.server.start()
        print(DateHelper.get_local_datetime(), self.__class__.__name__,
              " successful started")

    def stop(self):
        self.server.stop()
        print(DateHelper.get_local_datetime(), self.__class__.__name__,
              " successful stopped")
Example #12
0
class UAServer:
    def __init__(self,rack : rack_controller):
        self.rack = rack
        self._setup_nodes()
        self._generate_tags()

        self.ua_server.start()
        
        self._generate_subscriptions()
        Thread(target=self._var_updater, daemon=True).start()

    def _setup_nodes(self):        
        
        # Create server instance 
        self.ua_server = Server('./opcua_cache')
        self.ua_server.set_endpoint('opc.tcp://0.0.0.0:4840/UA/PickByLight')
        self.ua_server.set_server_name("Pick By Light Server")
        # idx name will be used later for creating the xml used in data type dictionary
        # setup our own namespace, not really necessary but should as spec
        idx_name = 'http://examples.freeopcua.github.io'
        self.idx = self.ua_server.register_namespace(idx_name)
        
        # Set all possible endpoint policies for clients to connect through
        self.ua_server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt,
            ua.SecurityPolicyType.Basic128Rsa15_Sign,
            ua.SecurityPolicyType.Basic256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256_Sign])

        # get Objects node, this is where we should put our custom stuff
        objects = self.ua_server.get_objects_node()
        # add a PackMLObjects folder
        pml_folder = objects.add_folder(self.idx, "PackMLObjects")
        # Get the base type object
        types = self.ua_server.get_node(ua.ObjectIds.BaseObjectType)
        # Create a new type for PackMLObjects
        PackMLBaseObjectType = types.add_object_type(self.idx, "PackMLBaseObjectType")

        # Create objects for the pack tags using the above created packMLBasedObjectType
        self.Admin = pml_folder.add_object('ns=2;s=Admin', "Admin", PackMLBaseObjectType.nodeid)
        self.Status = pml_folder.add_object('ns=2;s=Status', "Status", PackMLBaseObjectType.nodeid)
        self.Command = pml_folder.add_object('ns=2;s=Command', "Command", PackMLBaseObjectType.nodeid)

        # Create an object container for the rack
        self.RackStatus = self.Status.add_object('ns=2;s=Status.Rack', 'Rack')
        #BoxesCommonStatus = BoxesStatus.add_object('ns=2;s=Status.Boxes.Common', 'Common')

        root = self.ua_server.get_root_node()
        DummyFestoObj = root.add_object("ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables", "DummyFesto")
        DummyFestoObj.add_variable("ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables.FlexStationStatus", "FlexStationStatus", val=0).set_writable()
        DummyFestoObj.add_variable("ns=2;s=|var|CECC-LK.Application.FBs.stpStopper1.stAppControl.uiOpNo","uiOpNo", val=0).set_writable()
        

    def _generate_tags(self):
        # for all ports generate tags
        for port_number in self.rack.ports:
            # Make a folder with the port_number as the name
            b_obj = self.RackStatus.add_object('ns=2;s=Status.Rack.{}'.format(port_number), str(port_number))
            
            b_obj.add_variable("ns=2;s=Status.Rack.{}.Selected".format(port_number)             ,"Selected"         , bool())
            b_obj.add_variable("ns=2;s=Status.Rack.{}.Activity".format(port_number)             ,"Activity"         , bool())
            b_obj.add_variable("ns=2;s=Status.Rack.{}.ActivityTimestamp".format(port_number)    ,"ActivityTimestamp", datetime.fromtimestamp(0))
            b_obj.add_variable("ns=2;s=Status.Rack.{}.PickTimestamp".format(port_number)        ,"PickTimestamp"    , datetime.fromtimestamp(0))
            b_obj.add_variable("ns=2;s=Status.Rack.{}.LightState".format(port_number)           ,"LightState"       , bool())
            b_obj.add_variable("ns=2;s=Status.Rack.{}.BoxId".format(port_number)                ,"BoxId"            , str())
            b_obj.add_variable("ns=2;s=Status.Rack.{}.ContentId".format(port_number)            ,"ContentId"        , str())
            b_obj.add_variable("ns=2;s=Status.Rack.{}.ContentCount".format(port_number)         ,"ContentCount"     , int())

            '''
            create command tags for clients that does not support ua methods. 
            '''
        
        # create an object in the packml Command object called rack for all the commands. 
        b_obj = self.Command.add_object("ns=2;s=Command.Rack", 'Rack')
        # Create command tag for triggering the selection
        b_obj.add_variable("ns=2;s=Command.Rack.Select", 'Select', -1, ua.VariantType.Int16).set_writable()
        b_obj.add_variable("ns=2;s=Command.Rack.DeSelect", 'DeSelect', -1, ua.VariantType.Int16).set_writable()

    def _generate_subscriptions(self):
        # Create UA subscriber node for the box. Set self as handler.
        sub = self.ua_server.create_subscription(100, self)
 
        # Subscribe to the Select tag
        n = self.ua_server.get_node("ns=2;s=Command.Rack.Select")
        sub.subscribe_data_change(n)

        # Subscribe to the Deselect tag
        n = self.ua_server.get_node("ns=2;s=Command.Rack.DeSelect")
        sub.subscribe_data_change(n)
        pass

    def event_notification(self, event):
        print("Python: New event. No function implemented", event)

    def datachange_notification(self, node, val, data):
        """UA server callback on data change notifications
            This is a workaround for kepware that does not support 
            UA methods, so instead is has "trigger tags" that when 
            set to true it works like calling a method. 
            TODO make this more dynamic instead of hard coding the attributes. 
        
        Arguments:
            node {Node} -- [description]
            val {[type]} -- [description]
            data {[type]} -- [description]
        """

        # avoid triggereing it all again when resetting the tags to -1
        if val != -1 :          
            # Print info
            print("New data change event", node, val)
            # get the node browse name. 
            node_id = node.get_browse_name().Name
            # If the trigger tag changes to true go in and update the status tag and set the trigger back to false.
            # Also read description above. 
            if node_id == "Select" :
                self.rack.select_port(val)
                node.set_value(-1)
            elif node_id == "Deselect" :
                self.rack.select_port(val)
                node.set_value(-1)

    def _var_updater(self):
        while True:
            sleep(0.1)
            # for all boxes update tags
            for port_number, port in self.rack.ports.items():
                    
                # get the object in the packml status object using our unique idx
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.Activity".format(port_number))
                node.set_value(port.activity)          
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ActivityTimestamp".format(port_number))
                node.set_value(port.activity_timestamp) 
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.LightState".format(port_number))
                node.set_value(port.get_light())        

            for port_number, box in self.rack.boxes.items():    
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.BoxId".format(port_number))
                node.set_value(box.box_id)             
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ContentId".format(port_number))
                node.set_value(box.content_id)         
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ContentCount".format(port_number))
                node.set_value(box.content_count)        
            
            for port_number, select_state in self.rack.ports_select_state.items():
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.Selected".format(port_number))          
                node.set_value(select_state.selected)
                node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.PickTimestamp".format(port_number))  
                node.set_value(select_state.pick_timestamp)                   
Example #13
0
class OPCUAServer:
    """An OPC UA server which reads variables from a csv file and exposes it.

    Args:
        endpoint (:obj:`str`): OPC UA server endpoint. Defaults to
            'opc.tcp://0.0.0.0:4840/intry4.0/server/'.
        server_name (:obj:`str`): OPC UA server name. Defaults to
            'InTry 4.0 OPC UA Server'.
        security_policy (:obj:`list`): Array which contains
            `opcua.ua.SecurityPolicyType` available in the server. Defaults to
            [
                ua.SecurityPolicyType.NoSecurity,
                ua.SecurityPolicyType.Basic256Sha256_Sign,
                ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ]
        ns_uri(:obj:`str`): the namespace URI where all the variables will be added.
            Defaults to 'urn:intry4.0:server'.
        object_name(:obj:`str`): name of the OPC UA object that will be created to hold
            all variables. Defaults to 'variables'.
        last_row_file (:obj:`str`): name of the file in which the last row published by
            the server will be saved.
        certificate (:obj:`str`): path of the certificate file used by the server.
            Defaults to '/var/intry-opcua-server/cert.der'.
        private_key (:obj:`str`): path of the certificate file used by the server.
            Defaults to '/var/intry-opcua-server/key.pem'.
        min_time(:obj:`int`): min time elapsed between variable updates. Defaults to 30.
        logger(:obj:`logging.Logger`): logger to be used. Defaults to None.

    Attributes:
        _server (opcua.Server): the OPC UA server.
        endpoint (str): OPC UA server endpoint.
        _ns_index (): the namespace index where all the variables will be added.
        _object ()
        last_row (:obj:`dict`): last row that has been used by the server. For example:
            {
                "file": "csv1.csv",
                "row": "2019-10-02 23:55"
            }
        _stop (bool): flag variable that controls the infinite loop of variable
            updating.
    """

    def __init__(
        self,
        endpoint: str = "opc.tcp://0.0.0.0:4840/intry4.0/server/",
        server_name: str = "InTry 4.0 - OPC UA Server",
        security_policy: List[ua.SecurityPolicyType] = None,
        ns_uri: str = "urn:intry:opcua:server",
        object_name: str = "variables",
        last_row_file: str = "/var/intry-opcua-server/last_row.log",
        certificate: str = "/var/intry-opcua-server/cert.der",
        private_key: str = "/var/intry-opcua-server/key.pem",
        min_time: int = 30,
        logger=None,
    ):
        if security_policy is None:
            _security_policy = [
                ua.SecurityPolicyType.NoSecurity,
                ua.SecurityPolicyType.Basic256Sha256_Sign,
                ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ]

        self._server = Server()
        self.endpoint = endpoint
        self._server.set_endpoint(self.endpoint)
        self._server.set_security_policy(_security_policy)
        self._server.load_certificate(certificate)
        self._server.load_private_key(private_key)
        self._ns_index = self._server.register_namespace(ns_uri)
        self._object = self._server.nodes.objects.add_object(
            self._ns_index, object_name
        )
        self._last_row_file = last_row_file
        self._logger = logger or logging.getLogger(__name__)
        self.last_row = {}
        self._stop = False
        self.min_time = min_time

    def _add_variable(self, name, value):
        """Adds a variable to the OPC UA server.

        Args:
            name (:obj:`str`): name of the variable.
            value (int or float): initial value of the variable.

        Returns:
            opcua.common.node.Node: the created variable in the OPC UA server.
        """
        return self._object.add_variable(self._ns_index, name, value)

    def _get_csvs(self, csv_dir):
        """Get the CSV files stored in the specified directory and filter the CSV which
        are not required to start publishing new values from the last row that was
        published.

        Args:
            csv_dir (:obj:`str`): path of the directory containing CSVs.
        """
        self._read_last_row()
        csvs = get_csvs_in_dir(csv_dir)
        self._logger.debug(f"CSV files inside {csv_dir}: {len(csvs)}")

        if not self.last_row:
            df = pd.read_csv(csvs[0], index_col="date")
            self.last_row = {"file": csvs[0], "row": df.index[0]}

        file_index = csvs.index(self.last_row["file"])
        return csvs[file_index:]

    def variable_values_from_csvs(self, csv_dir):
        """Creates variables inside the OPC UA server from the CSVs contained in the
        specified directory. Then, each row of the provided CSVs will be read to update
        the value of each variable.

        csv_dir (str): path of the directory containing CSVs.
        """
        csvs = self._get_csvs(csv_dir)
        len_csvs = len(csvs)
        if len_csvs > 0:
            variable_name_node = {}
            for (index, csv) in enumerate(csvs):
                if self._stop:
                    break

                self._logger.info(f"Reading file {csv}")
                df = pd.read_csv(csv, index_col="date")
                self.last_row["file"] = csv

                # If first CSV, create variables in the OPC UA Server
                if index == 0:
                    self._logger.debug(
                        f"First csv readed: {csv}. Creating {len(df.columns)} OPC UA variables from it..."
                    )
                    df = df[self.last_row["row"] :]

                    for column in df.columns:
                        first_value = df[column].iloc[0]
                        self._logger.debug(
                            f"Adding variable [{column}] with initial value <{first_value}>"
                        )
                        variable_name_node[column] = self._add_variable(
                            column, first_value
                        )

                    # remove the first row because its going used for initial value
                    df = df.iloc[1:]

                # iterate over the rows in the dataframe for updating the value of each variable
                time_between_update = 0
                last_index = None
                for (index, row) in df.iterrows():
                    if self._stop:
                        break

                    self.last_row["row"] = index

                    # Calculate the time to sleep between each update with the date of the
                    # last row and this row.
                    if last_index is not None:
                        time_between_update = (
                            str_to_date(index) - str_to_date(last_index)
                        ).total_seconds()

                        if time_between_update > 60:
                            self._logger.info(
                                "Time between update too high. Setting it to 60 secs..."
                            )
                            time_between_update = 60.0

                        elif time_between_update < self.min_time:
                            self._logger.info(
                                f"Time between update was negative or too low. Setting it to {self.min_time} secs..."
                            )
                            time_between_update = self.min_time

                    self._logger.info(f"Starting sleep of {time_between_update}...")
                    time.sleep(time_between_update)
                    self._logger.info(
                        f"Time of {time_between_update} elapsed. Updating variable values..."
                    )
                    for (column, node) in variable_name_node.items():
                        node.set_value(row[column])

                    last_index = index

    def _write_last_row(self):
        """Writes the last row published to a file in JSON format."""
        create_path_if_not_exists(self._last_row_file)
        with open(self._last_row_file, "w+") as f:
            f.write(json.dumps(self.last_row))

    def _read_last_row(self):
        """Reads the last row published from a JSON file."""
        if file_exists(self._last_row_file):
            self._logger.info(f"Reading last row file {self._last_row_file}")
            with open(self._last_row_file, "r") as f:
                self.last_row = json.loads(f.read())
        else:
            self._logger.info(f"File {self._last_row_file} does not exist")
            self.last_row = {}

    def start(self):
        """Starts the OPC UA server execution."""
        self._logger.info(f"Starting OPC UA server. Listening on {self.endpoint}")
        self._server.start()

    def stop(self):
        """Stops the OPC UA server execution."""
        self._write_last_row()
        self._logger.info("Stopping OPC UA server...")
        self._stop = True
        self._server.stop()
Example #14
0
class ServerClass:
    def define_server(self):
        """
        Function for setting up the OPC UA Server.

        """
        #  Instanciation of OPC-UA Server
        self.server = Server()        
        self.server.set_endpoint("opc.tcp://0.0.0.0:4840/")
        self.server.set_server_name('Opc UA Valve Test Server')
        # set all possible endpoint policies for clients to connect through
        self.server.set_security_policy([
                    ua.SecurityPolicyType.NoSecurity,
                    ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
                    ua.SecurityPolicyType.Basic256Sha256_Sign])       
        
        # setup our own namespace
        self.uri = "http://test.valve.iit"
        self.idx = self.server.register_namespace(self.uri)
        
        # Create a new node type we can instantiate in address space
        self.dev = self.server.nodes.base_object_type.add_object_type(self.idx,
                                                                      "Test Server")
        
        self.valve01 = self.server.nodes.objects.add_object(self.idx,
                                                    'Valve01')

        
        #  Definition of the pickle file
        with open('pickles/valve01.p', 'rb') as handle:
            self.valve_prop = pickle.load(handle)
        
        #  Definition of the OPC UA classes and variables
        self.typ_valve01 = self.valve01.add_property(self.idx, "ValveType",
                                                     self.valve_prop['typ'],
                                                     ua.VariantType.String)
        
        self.medium_valve01 = self.valve01.add_property(self.idx, "Medium",
                                                        self.valve_prop['medium'],
                                                        ua.VariantType.String)

        self.status_valve01 = self.valve01.add_variable(self.idx, "Status",
                                                        self.valve_prop['status'],
                                                        ua.VariantType.String)
        self.status_valve01.set_writable()
        
        self.accuracy_valve01 = self.valve01.add_variable(self.idx, "Accuracy",
                                                          self.valve_prop['accuracy'],
                                                          ua.VariantType.Double)
        self.accuracy_valve01.set_writable()
        
        self.status_update_valve01 = self.valve01.add_variable(self.idx, "LastUpdate",
                                                               self.valve_prop['updated'],
                                                               ua.VariantType.DateTime)
        self.status_update_valve01.set_writable()  
        
        self.cycles_valve01 = self.valve01.add_variable(self.idx, 'TotalCycles',
                                                        self.valve_prop['cycles'],
                                                        ua.VariantType.Int64)
        self.cycles_valve01.set_writable() 
        
        self.server.start()
    
    def use_server(self, status, updated, accuracy, cycles):
        """
        Function for updating the OPC UA Server.

        """
        self.status_valve01.set_value(status)
        self.status_update_valve01.set_value(updated)
        self.accuracy_valve01.set_value(accuracy)
        self.cycles_valve01.set_value(cycles)
    
    def stop_server(self):
        """
        Function for stopping the OPC UA Server.

        """
        self.server.stop()
Example #15
0
    #logger = logging.getLogger("opcua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("opcua.uaprocessor")
    # logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    #server.disable_clock()
    #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")
    # set all possible endpoint policies for clients to connect through
    server.set_security_policy([
        ua.SecurityPolicyType.NoSecurity,
        ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt,
        ua.SecurityPolicyType.Basic128Rsa15_Sign,
        ua.SecurityPolicyType.Basic256_SignAndEncrypt,
        ua.SecurityPolicyType.Basic256_Sign
    ])

    # setup our own namespace
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # create a new node type we can instantiate in our address space
    dev = server.nodes.base_object_type.add_object_type(0, "MyDevice")
    dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True)
    dev.add_property(0, "device_id", "0340").set_modelling_rule(True)
    ctrl = dev.add_object(0, "controller")
    ctrl.set_modelling_rule(True)
    ctrl.add_property(0, "state", "Idle").set_modelling_rule(True)
Example #16
0
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("opcua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("opcua.uaprocessor")
    # logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    #server.disable_clock()
    #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")
    # set all possible endpoint policies for clients to connect through
    server.set_security_policy([
                ua.SecurityPolicyType.NoSecurity,
                ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt,
                ua.SecurityPolicyType.Basic128Rsa15_Sign,
                ua.SecurityPolicyType.Basic256_SignAndEncrypt,
                ua.SecurityPolicyType.Basic256_Sign])

    # setup our own namespace
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # create a new node type we can instantiate in our address space
    dev = server.nodes.base_object_type.add_object_type(0, "MyDevice")
    dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True)
    dev.add_property(0, "device_id", "0340").set_modelling_rule(True)
    ctrl = dev.add_object(0, "controller")
    ctrl.set_modelling_rule(True)
    ctrl.add_property(0, "state", "Idle").set_modelling_rule(True)
class OpcUaConnectorGeneralTest(ConnectorTestBase):
    def test_number_one(self):
        self._create_connector("connection_test.json")
        self.assertTrue(self.connector is not None)
        self.check_or_create_server()
        self.connector.open()



    def check_or_create_server(self):
        if not hasattr(self, "test_server"):
            self.test_server = Server()
            self.__server_thread = Thread(target=self.__server_run, name="Test OPC UA server", args=(self.test_server,))
        self.assertTrue(self.test_server is not None)


    def __server_run(self, test_server):
        self.test_server = test_server
        class SubHandler(object):
            
            def datachange_notification(self, node, val, data):
                print("Python: New data change event", node, val)
                
            def event_notification(self, event):
                print("Python: New event", event)

        @uamethod
        def multiply(parent, x, y):
            return x * y

        self.test_server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
        self.test_server.set_server_name("Test Server")
        self.test_server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign])

        uri = "http://127.0.0.1"

        idx = self.test_server.register_namespace(uri)
        device = self.test_server.nodes.objects.add_object(idx, "Device1")
        name = self.test_server.nodes.objects.add_variable(idx, "serialNumber", "TEST")
        name.set_writable()
        temperature_and_humidity = device.add_object(idx, "TemperatureAndHumiditySensor")
        temperature = temperature_and_humidity.add_variable(idx, "Temperature", 56.7)
        humidity = temperature_and_humidity.add_variable(idx, "Humidity", 68.7)
        battery = device.add_object(idx, "Battery")
        battery_level = battery.add_variable(idx, "batteryLevel", 24)
        device.add_method(idx, "multiply", multiply, [ua.VariantType.Int64, ua.VariantType.Int64], [ua.VariantType.Int64])

        self.test_server.start()
        try:
            while self.server_running:
                sleep(.1)
        finally:
            self.test_server.stop()

    def stop_test_server(self):
        self.server_running = False

    def tearDown(self):
        super().tearDown()
        self.stop_test_server()
Example #18
0
class UA_Object(object):
    def __init__(self, url, spaceName, security_num):
        self.server = Server()
        self.endPoint = self.server.set_endpoint(url)
        self.security_num = security_num
        self.spaceName = self.server.register_namespace(spaceName)
        self.node_obj = self.server.get_objects_node()  # root_id

    def set_security(self):
        security = [
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign
        ]
        self.server.set_security_policy([security[self.security_num]])

    def read_json(self, jsonPath):
        with open(jsonPath, 'r') as f:
            data = f.read()
            return json.loads(data)

    def get_server_tagName(self, jsonDict):
        s_server_tag = UAStack()
        for k, v in jsonDict.items():
            for i, j in v.items():
                s_server_tag.push({k: i})
        return s_server_tag

    def add_serverName(self, s_tags):
        temp = list()
        for k in s_tags.keys():
            serverObj = self.node_obj.add_object(self.spaceName, str(k))
            temp.append(serverObj)
        return temp

    def get_browse_name(self, tagNameObj):
        temp = list()
        for nodeObj in tagNameObj:
            tag_TagName = nodeObj.get_browse_name().Name
            temp.append(tag_TagName)
        return temp

    def add_tagName(self, s_tags, serverObj):
        tagNameObj = list()
        for val in s_tags:
            for q, w in val.items():
                for i in serverObj:
                    serverName = i.get_browse_name().Name
                    if serverName == q:
                        tag = i.add_variable(self.spaceName, w, None)
                        tag.set_writable()
                        tagNameObj.append(tag)
        return tagNameObj

    def change_node(self, res_stack, tagNodeObj):
        for tagObj in tagNodeObj:
            b_name = tagObj.get_browse_name().Name
            for values in res_stack:
                if b_name in values:
                    tagObj.set_value(values[b_name])
                    break