Beispiel #1
1
def uawrite():
    parser = argparse.ArgumentParser(description="Write attribute of a node, per default write value of node")
    add_common_args(parser)
    parser.add_argument("-a",
                        "--attribute",
                        dest="attribute",
                        type=int,
                        #default="VALUE",
                        #choices=['VALUE', 'NODEID', 'BROWSENAME', 'ERROR', 'CRITICAL'],
                        default=ua.AttributeIds.Value,
                        help="Set attribute to read")
    parser.add_argument("-l",
                        "--list",
                        "--array",
                        dest="array",
                        default="guess",
                        choices=["guess", "true", "false"],
                        help="Value is an array")
    parser.add_argument("-t",
                        "--datatype",
                        dest="datatype",
                        default="guess",
                        choices=["guess", 'byte', 'sbyte', 'nodeid', 'expandednodeid', 'qualifiedname', 'browsename', 'string', 'float', 'double', 'int16', 'int32', "int64", 'uint16', 'uint32', 'uint64', "bool", "string", 'datetime', 'bytestring', 'xmlelement', 'statuscode', 'localizedtext'],  
                        help="Data type to return")
    parser.add_argument("value",
                        help="Value to be written",
                        metavar="VALUE")
    args = parser.parse_args()
    if args.nodeid == "i=84" and args.path == "" and args.attribute == ua.AttributeIds.Value:
        parser.print_usage()
        print("uaread: error: A NodeId or BrowsePath is required")
        sys.exit(1)
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = client.get_node(args.nodeid)
        if args.path:
            node = node.get_child(args.path.split(","))
        val = _val_to_variant(args.value, args)
        node.set_attribute(args.attribute, ua.DataValue(val))
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #2
0
def uals():
    parser = argparse.ArgumentParser(description="Browse OPC-UA node and print result")
    add_common_args(parser)
    parser.add_argument("-l",
                        dest="long_format",
                        const=3,
                        nargs="?",
                        type=int,
                        help="use a long listing format")
    parser.add_argument("-d",
                        "--depth",
                        default=1,
                        type=int,
                        help="Browse depth")

    args = parse_args(parser)
    if args.long_format is None:
        args.long_format = 1

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    client.connect()
    try:
        node = get_node(client, args)
        print("Browsing node {0} at {1}\n".format(node, args.url))
        if args.long_format == 0:
            _lsprint_0(node, args.depth - 1)
        elif args.long_format == 1:
            _lsprint_1(node, args.depth - 1)
        else:
            _lsprint_long(node, args.depth - 1)
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #3
0
def uaclient():
    parser = argparse.ArgumentParser(description="Connect to server and start python shell. root and objects nodes are available. Node specificed in command line is available as mynode variable")
    add_common_args(parser)
    parser.add_argument("-c",
                        "--certificate",
                        help="set client certificate")
    parser.add_argument("-k",
                        "--private_key",
                        help="set client private key")
    args = parse_args(parser)

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    if args.certificate:
        client.load_client_certificate(args.certificate)
    if args.private_key:
        client.load_private_key(args.private_key)
    client.connect()
    try:
        root = client.get_root_node()
        objects = client.get_objects_node()
        mynode = get_node(client, args)
        embed()
    finally:
        client.disconnect()
    sys.exit(0)
Beispiel #4
0
 def test_find_servers2(self):
     client = Client(self.discovery.endpoint.geturl())
     client.connect()
     try:
         servers = client.find_servers()
         new_app_uri1 = "urn:freeopcua:python:server:test_discovery1"
         self.srv.application_uri = new_app_uri1
         self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0)
         new_app_uri2 = "urn:freeopcua:python:test_discovery2"
         self.srv.application_uri = new_app_uri2
         self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0)
         time.sleep(0.1) # let server register registration
         new_servers = client.find_servers()
         self.assertEqual(len(new_servers) - len(servers) , 2)
         self.assertFalse(new_app_uri1 in [s.ApplicationUri for s in servers])
         self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in servers])
         self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
         self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers])
         # now do a query with filer
         new_servers = client.find_servers(["urn:freeopcua:python:server"])
         self.assertEqual(len(new_servers) - len(servers) , 0)
         self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
         self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in new_servers])
         # now do a query with filer
         new_servers = client.find_servers(["urn:freeopcua:python"])
         self.assertEqual(len(new_servers) - len(servers) , 2)
         self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
         self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers])
     finally:
         client.disconnect()
 def wrapper(self):
     try:
         client = Client(URL)
         client.connect()
         func(self, client)
     finally:
         client.disconnect()
 def test_nocrypto(self):
     clt = Client(self.uri_no_crypto)
     clt.connect()
     try:
         clt.get_objects_node().get_children()
     finally:
         clt.disconnect()
 def test_find_servers2(self):
     client = Client(self.discovery.endpoint.geturl())
     client.connect()
     try:
         servers = client.find_servers()
         # Use 2 different RegistrationServices, as it does not allow duplicate registrations.
         with RegistrationService() as regService1, RegistrationService() as regService2:
             # Register to server with uri1
             new_app_uri1 = "urn:freeopcua:python:server:test_discovery1"
             self.srv.application_uri = new_app_uri1
             regService1.register_to_discovery(self.srv, self.discovery.endpoint.geturl(), period=0)
             # Register to server with uri2
             new_app_uri2 = "urn:freeopcua:python:test_discovery2"
             self.srv.application_uri = new_app_uri2
             regService2.register_to_discovery(self.srv, self.discovery.endpoint.geturl(), period=0)
             # Check for 2 registrations
             time.sleep(0.1)  # let server register registration
             new_servers = client.find_servers()
             self.assertEqual(len(new_servers) - len(servers) , 2)
             self.assertFalse(new_app_uri1 in [s.ApplicationUri for s in servers])
             self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in servers])
             self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
             self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers])
             # now do a query with filter
             new_servers = client.find_servers(["urn:freeopcua:python:server"])
             self.assertEqual(len(new_servers) - len(servers) , 0)
             self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
             self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in new_servers])
             # now do a query with filter
             new_servers = client.find_servers(["urn:freeopcua:python"])
             self.assertEqual(len(new_servers) - len(servers) , 2)
             self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers])
             self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers])
     finally:
         client.disconnect()
Beispiel #8
0
def uaread():
    parser = argparse.ArgumentParser(description="Read attribute of a node, per default reads value of a node")
    add_common_args(parser)
    parser.add_argument("-a",
                        "--attribute",
                        dest="attribute",
                        type=int,
                        default=ua.AttributeIds.Value,
                        help="Set attribute to read")
    parser.add_argument("-t",
                        "--datatype",
                        dest="datatype",
                        default="python",
                        choices=['python', 'variant', 'datavalue'],
                        help="Data type to return")

    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    client.set_security_string(args.security)
    client.connect()

    try:
        node = get_node(client, args)
        attr = node.get_attribute(args.attribute)
        if args.datatype == "python":
            print(attr.Value.Value)
        elif args.datatype == "variant":
            print(attr.Value)
        else:
            print(attr)
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #9
0
def uasubscribe():
    parser = argparse.ArgumentParser(description="Subscribe to a node and print results")
    add_common_args(parser)
    parser.add_argument("-t",
                        "--eventtype",
                        dest="eventtype",
                        default="datachange",
                        choices=['datachange', 'event'],
                        help="Event type to subscribe to")

    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = get_node(client, args)
        handler = SubHandler()
        sub = client.create_subscription(500, handler)
        if args.eventtype == "datachange":
            sub.subscribe_data_change(node)
        else:
            sub.subscribe_events(node)
        embed()
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #10
0
def uals():
    parser = argparse.ArgumentParser(description="Browse OPC-UA node and print result")
    add_common_args(parser)
    #parser.add_argument("-l",
                        #dest="long_format",
                        #default=ua.AttributeIds.Value,
                        #help="use a long listing format")
    parser.add_argument("-d",
                        "--depth",
                        default=1,
                        type=int,
                        help="Browse depth")

    args = parser.parse_args()
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = client.get_node(args.nodeid)
        if args.path:
            node = node.get_child(args.path.split(","))
        print("Browsing node {} at {}\n".format(node, args.url))
        _lsprint(client, node.nodeid, args.depth - 1)

    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #11
0
def uahistoryread():
    parser = argparse.ArgumentParser(description="Read history of a node")
    add_common_args(parser)
    parser.add_argument(
        "--starttime", default="", help="Start time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time"
    )
    parser.add_argument(
        "--endtime", default="", help="End time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time"
    )

    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    client.set_security_string(args.security)
    client.connect()
    try:
        node = get_node(client, args)
        starttime = str_to_datetime(args.starttime)
        endtime = str_to_datetime(args.endtime)
        print(
            "Reading raw history of node {} at {}; start at {}, end at {}\n".format(node, args.url, starttime, endtime)
        )
        print_history(node.read_raw_history(starttime, endtime))
    finally:
        client.disconnect()
    sys.exit(0)
Beispiel #12
0
def uasubscribe():
    parser = argparse.ArgumentParser(description="Subscribe to a node and print results")
    add_common_args(parser)
    parser.add_argument("-t",
                        "--eventtype",
                        dest="eventtype",
                        default="datachange",
                        choices=['datachange', 'event'],
                        help="Event type to subscribe to")

    args = parse_args(parser, requirenodeid=False)
    if args.eventtype == "datachange":
        _require_nodeid(parser, args)
    else:
        # FIXME: this is broken, someone may have written i=84 on purpose
        if args.nodeid == "i=84" and args.path == "":
            args.nodeid = "i=2253"

    client = Client(args.url, timeout=args.timeout)
    client.set_security_string(args.security)
    client.connect()
    try:
        node = get_node(client, args)
        handler = SubHandler()
        sub = client.create_subscription(500, handler)
        if args.eventtype == "datachange":
            sub.subscribe_data_change(node)
        else:
            sub.subscribe_events(node)
        embed()
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #13
0
def uaclient():
    parser = argparse.ArgumentParser(description="Connect to server and start python shell. root and objects nodes are available. Node specificed in command line is available as mynode variable")
    add_common_args(parser)
    parser.add_argument("-c",
                        "--certificate",
                        help="set client certificate")
    parser.add_argument("-k",
                        "--private_key",
                        help="set client private key")
    args = parser.parse_args()
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    if args.certificate:
        client.load_certificate(args.certificate)
    if args.private_key:
        client.load_certificate(args.private_key)
    try:
        root = client.get_root_node()
        objects = client.get_objects_node()
        mynode = client.get_node(args.nodeid)
        if args.path:
            mynode = mynode.get_child(args.path.split(","))
        embed()
    finally:
        client.disconnect()
    sys.exit(0)
Beispiel #14
0
def uasubscribe():
    parser = argparse.ArgumentParser(description="Subscribe to a node and print results")
    add_common_args(parser)
    parser.add_argument("-t",
                        "--eventtype",
                        dest="eventtype",
                        default="datachange",
                        choices=['datachange', 'event'],
                        help="Event type to subscribe to")

    args = parser.parse_args()
    if args.nodeid == "i=84" and args.path == "":
        parser.print_usage()
        print("uaread: error: The NodeId or BrowsePath of a variable is required")
        sys.exit(1)
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = client.get_node(args.nodeid)
        if args.path:
            node = node.get_child(args.path.split(","))
        handler = SubHandler()
        sub = client.create_subscription(500, handler)
        if args.eventtype == "datachange":
            sub.subscribe_data_change(node)
        else:
            sub.subscribe_events(node)
        embed()
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
def run():
    configs = get_configs()
    
    patterns = configs["measures"].split(":")
    tout = configs["connection_timeout"].strip()
    timeout = 1 if len(tout) <= 0 else int(tout)

    client = Client(configs["connection"], timeout=timeout)
    
    try:
        client.connect()
        measures = []
        root = client.get_root_node()
        collect_measures(measures, patterns, root)
        
        for x in root.get_children():
            print x.get_browse_name().Name
            
        for m in measures:
            print m
            
        time.sleep(30)
    except Exception as ex:
        print ex
    finally:
        client.disconnect()
Beispiel #16
0
def uahistoryread():
    parser = argparse.ArgumentParser(description="Read history of a node")
    add_common_args(parser)
    parser.add_argument("--starttime",
                        default="",
                        help="Start time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time")
    parser.add_argument("--endtime",
                        default="",
                        help="End time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time")

    args = parser.parse_args()
    if args.nodeid == "i=84" and args.path == "":
        parser.print_usage()
        print("uahistoryread: error: A NodeId or BrowsePath is required")
        sys.exit(1)
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = client.get_node(args.nodeid)
        if args.path:
            node = node.get_child(args.path.split(","))
        starttime = str_to_datetime(args.starttime)
        endtime = str_to_datetime(args.endtime)
        print("Reading raw history of node {} at {}; start at {}, end at {}\n".format(node, args.url, starttime, endtime))
        print_history(node.read_raw_history(starttime, endtime))
    finally:
        client.disconnect()
    sys.exit(0)
Beispiel #17
0
class TestClient(unittest.TestCase, CommonTests):
    '''
    Run common tests on client side
    Of course we need a server so we start a server in another 
    process using python Process module
    Tests that can only be run on client side must be defined here
    '''
    @classmethod
    def setUpClass(self):
        # start our own server
        self.srv = Server() 
        self.srv.set_endpoint('opc.tcp://localhost:%d' % port_num1)
        add_server_methods(self.srv)
        self.srv.start()

        # start client
        self.clt = Client('opc.tcp://localhost:%d' % port_num1)
        self.clt.connect()
        self.opc = self.clt

    @classmethod
    def tearDownClass(self):
        self.clt.disconnect()
        # stop the server in its own process
        self.srv.stop()

    def test_service_fault(self):
        request = ua.ReadRequest()
        request.TypeId = ua.FourByteNodeId(999) # bad type!
        with self.assertRaises(Exception):
            self.clt.bclient._send_request(request)
 def test_basic256(self):
     clt = Client(self.uri_crypto)
     try:
         clt.set_security_string("Basic256,Sign,examples/example-certificate.der,examples/example-private-key.pem")
         clt.connect()
         self.assertTrue(clt.get_objects_node().get_children())
     finally:
         clt.disconnect()
 def test_basic128Rsa15_encrypt(self):
     clt = Client(self.uri_crypto)
     try:
         clt.set_security_string("Basic128Rsa15,SignAndEncrypt,examples/certificate-example.der,examples/private-key-example.pem")
         clt.connect()
         self.assertTrue(clt.get_objects_node().get_children())
     finally:
         clt.disconnect()
class HelloClient:
    def __init__(self, endpoint):
        self.client = Client(endpoint)

    def __enter__(self):
        self.client.connect()
        return self.client

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.client.disconnect()
Beispiel #21
0
    def opcua_init(request):

        client = Client(
            request.get('url', 'opc.tcp://localhost:4841'),
            timeout=request.get('timeout', 10)
        )
        client.set_security_string(request.get('security', ''))
        client.connect()

        return client
 def test_basic256_encrypt_success(self):
     clt = Client(self.uri_crypto)
     try:
         clt.set_security(security_policies.SecurityPolicyBasic256,
                          'examples/certificate-example.der',
                          'examples/private-key-example.pem',
                          None,
                          ua.MessageSecurityMode.SignAndEncrypt
                          )
         clt.connect()
         self.assertTrue(clt.get_objects_node().get_children())
     finally:
         clt.disconnect()
Beispiel #23
0
 def test_discovery(self):
     client = Client(self.discovery.endpoint.geturl())
     client.connect()
     servers = client.find_servers()
     new_app_uri = "urn:freeopcua:python:server::test_discovery"
     self.srv.application_uri = new_app_uri
     self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 1)
     time.sleep(0.1) # let server register registration
     new_servers = client.find_servers()
     self.assertEqual(len(new_servers) - len(servers) , 1)
     self.assertFalse(new_app_uri in [s.ApplicationUri for s in servers])
     self.assertTrue(new_app_uri in [s.ApplicationUri for s in new_servers])
     client.disconnect()
class ServerC(object):
    def __init__(self):
        self._server = None
        self._client = None
        self.nodes = None
        self.get_node = None
        self.get_namespace_array = None

    def start_server(self, endpoint):
        self._server = UAServer()
        self._server.endpoint = 48400  # enpoint not supported yet
        #self._server.endpoint = endpoint
        self._server.start()
        #self._server.set_server_name("OpcUa Modeler Server")
        time.sleep(0.2)
        self._client = Client(endpoint)
        self._client.connect()

        self.nodes = self._client.nodes
        self.get_node = self._client.get_node
        self.get_namespace_array = self._client.get_namespace_array
        # now remove freeopcua namespace, not necessary when modeling and
        # ensures correct idx for exported nodesets
        ns_node = self._client.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
        nss = ns_node.get_value()
        #ns_node.set_value(nss[1:])

    def stop_server(self):
        if self._server is not None:
            self._client.disconnect()
            self._client = None
            self._server.stop()
            time.sleep(0.2)
            self._server = None
            self.get_node = None
            self.get_namespace_array = None

    def import_xml(self, path):
        return self._client.import_xml(path)

    def export_xml(self, nodes, uris, path):
        exp = XmlExporter(self._client)
        exp.build_etree(nodes, uris=uris)
        exp.write_xml(path)
Beispiel #25
0
def uaread():
    parser = argparse.ArgumentParser(description="Read attribute of a node, per default reads value of a node")
    add_common_args(parser)
    parser.add_argument("-a",
                        "--attribute",
                        dest="attribute",
                        type=int,
                        #default="VALUE",
                        #choices=['VALUE', 'NODEID', 'BROWSENAME', 'ERROR', 'CRITICAL'],
                        default=ua.AttributeIds.Value,
                        help="Set attribute to read")
    parser.add_argument("-t",
                        "--datatype",
                        dest="datatype",
                        default="python",
                        choices=['python', 'variant', 'datavalue'],
                        help="Data type to return")

    args = parser.parse_args()
    if args.nodeid == "i=84" and args.path == "" and args.attribute == ua.AttributeIds.Value:
        parser.print_usage()
        print("uaread: error: A NodeId or BrowsePath is required")
        sys.exit(1)
    logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))

    client = Client(args.url, timeout=args.timeout)
    client.connect()
    try:
        node = client.get_node(args.nodeid)
        if args.path:
            node = node.get_child(args.path.split(","))
        attr = node.get_attribute(args.attribute)
        if args.datatype == "python":
            print(attr.Value.Value)
        elif args.datatype == "variant":
            print(attr.Value)
        else:
            print(attr)
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #26
0
def uawrite():
    parser = argparse.ArgumentParser(description="Write attribute of a node, per default write value of node")
    add_common_args(parser)
    parser.add_argument("-a",
                        "--attribute",
                        dest="attribute",
                        type=int,
                        default=ua.AttributeIds.Value,
                        help="Set attribute to read")
    parser.add_argument("-l",
                        "--list",
                        "--array",
                        dest="array",
                        default="guess",
                        choices=["guess", "true", "false"],
                        help="Value is an array")
    parser.add_argument("-t",
                        "--datatype",
                        dest="datatype",
                        default="guess",
                        choices=["guess", 'byte', 'sbyte', 'nodeid', 'expandednodeid', 'qualifiedname', 'browsename', 'string', 'float', 'double', 'int16', 'int32', "int64", 'uint16', 'uint32', 'uint64', "bool", "string", 'datetime', 'bytestring', 'xmlelement', 'statuscode', 'localizedtext'],
                        help="Data type to return")
    parser.add_argument("value",
                        help="Value to be written",
                        metavar="VALUE")
    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    client.connect()
    try:
        node = get_node(client, args)
        val = _val_to_variant(args.value, args)
        node.set_attribute(args.attribute, ua.DataValue(val))
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #27
0
def uahistoryread():
    parser = argparse.ArgumentParser(description="Read history of a node")
    add_common_args(parser)
    parser.add_argument("--starttime",
                        default=None,
                        help="Start time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time - one day")
    parser.add_argument("--endtime",
                        default=None,
                        help="End time, formatted as YYYY-MM-DD [HH:MM[:SS]]. Default: current time")
    parser.add_argument("-e",
                        "--events",
                        action="store_true",
                        help="Read event history instead of data change history")
    parser.add_argument("-l",
                        "--limit",
                        type=int,
                        default=10,
                        help="Maximum number of notfication to return")

    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    client.connect()
    try:
        node = get_node(client, args)
        starttime = str_to_datetime(args.starttime, datetime.utcnow() - timedelta(days=1))
        endtime = str_to_datetime(args.endtime, datetime.utcnow())
        print("Reading raw history of node {0} at {1}; start at {2}, end at {3}\n".format(node, args.url, starttime, endtime))
        if args.events:
            evs = node.read_event_history(starttime, endtime, numvalues=args.limit)
            for ev in evs:
                print(ev)
        else:
            print_history(node.read_raw_history(starttime, endtime, numvalues=args.limit))
    finally:
        client.disconnect()
    sys.exit(0)
Beispiel #28
0
def uageneratestructs():
    parser = argparse.ArgumentParser(description="Generate a Python module from the xml structure definition (.bsd)")
    add_common_args(parser, require_node=True)
    parser.add_argument("-o",
                        "--output",
                        dest="output_path",
                        required=True,
                        type=str,
                        default=None,
                        help="The python file to be generated.",
                        )
    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    client.connect()
    try:
        node = get_node(client, args)
        generators, _ = client.load_type_definitions([node])
        generators[0].save_to_file(args.output_path, True)
    finally:
        client.disconnect()
    sys.exit(0)
    def test_context_manager(self):
        """ Context manager calls connect() and disconnect()
        """
        state = [0]
        def increment_state(self, *args, **kwargs):
            state[0] += 1

        # create client and replace instance methods with dummy methods
        client = Client('opc.tcp://dummy_address:10000')
        client.connect    = increment_state.__get__(client)
        client.disconnect = increment_state.__get__(client)

        assert state[0] == 0
        with client:
            # test if client connected
            self.assertEqual(state[0], 1)
        # test if client disconnected
        self.assertEqual(state[0], 2)
Beispiel #30
0
class CommunicationManager():
    def __init__(self, swtid="001", configObject=None):
        self.swtID = swtid
        self.mqttClient = None
        self.opcClient = None
        self.__stopFlag = False
        self.__valueQueue = queue.Queue()
        self.__startMQTTThread = Thread(target=self.__MQTT_startClient,
                                        args=(),
                                        name="StartMqttClient")
        self.__startOpcuaThread = None
        self.__startOpcuaWrite = None
        self.__nodeList = ["Wrong", "Entries"]
        self.__combinedNuelleData = NuelleData()
        self.Station5APresent = [False]

    ######### MQTT Methods ###########

    def __on_message(self, mqttc, obj, msg):
        # statt topic wahrscheinlich topic+fieldname, als Payload Feld6-8 aus den einzelnen topics (10 verschiedene features insg)
        #print(msg.topic + msg.payload.decode())
        self.__valueQueue.put(
            (msg.topic, msg.payload.decode())
        )  #msg.payload is bytes, use "decode()" turn it into string.   do not use str()

    def MQTT_CreateClient(self, url, port, timeout):
        self.mqttClient = mqtt.Client()
        self.mqttClient.on_message = self.__on_message
        self.mqttClient.connect(url, port, timeout)

    def MQTT_subscribeToTopic(self, topics):
        for topic in topics:
            self.mqttClient.subscribe(topic, 0)

    def MQTT_startClient(self):
        self.__startMQTTThread = Thread(target=self.__MQTT_startClient,
                                        args=(),
                                        name="StartMqttClient")
        self.__startMQTTThread.start()

    def __MQTT_startClient(self):
        self.mqttClient.loop_forever()

    def MQTT_stopClient(self):
        self.__MQTT_stopClient()

    def __MQTT_stopClient(self):
        try:
            self.mqttClient.disconnect()
            logging.info('Disconnected successfully')
        except:
            logging.error('Disconnect from MQTT Broker failed')
        self.__startMQTTThread.join()

    ######### OPC UA Methods ###########

    def OPCUA_createClient(self, url):
        self.opcClient = Client(url)
        self.opcClient.connect()
        print("OPC UA Client is now connected to " + url)

    def OPCUA_subscribe(self, nodeList):
        self.__nodeList = nodeList
        self.__startOpcuaThread = Thread(target=self.__OPCUA_subscribe,
                                         args=(),
                                         name="StartOPCUAClient")
        self.__startOpcuaThread.start()

    def OPCUA_write(self, nodeIDtoWrite, valueToWrite):
        print("OPC UA write to   ")
        print(nodeIDtoWrite)
        print("   with value:  ")
        print(valueToWrite)
        #self.__startOpcuaWriteThread = Thread(target=self.__OPCUA_write, args=(nodeIDtoWrite, valueToWrite),
        #                                      name="WriteToOPCUAClient"+str(nodeIDtoWrite))
        #self.__startOpcuaWriteThread.start()
        #self.__startOpcuaWriteThread.join()

    def __OPCUA_write(self, nodeID, value):
        var = self.opcClient.get_node(nodeID)
        var.set_attribute(ua.AttributeIds.Value, ua.DataValue(value))

    def __OPCUA_subscribe(self):
        handler = SubHandler(self.__valueQueue, self.Station5APresent)
        self.__subscription = self.opcClient.create_subscription(50, handler)
        for i in range(len(self.__nodeList)):
            node = self.opcClient.get_node(self.__nodeList[i])
            self.__subscription.subscribe_data_change(node)

    def OPCUA_stopClient(self):
        self.__OPCUA_stopClient()

    def __OPCUA_stopClient(self):
        try:
            self.__subscription.delete()
            self.opcClient.disconnect()
            print('Disconnected successfully')
        except:
            print('Disconnect from opc ua server failed')

    ########## Handle Data Collection, Combination and Retrieving ###########

    def __addToNuelleData(self, ValueName, newValue):
        if ValueName == 'esp32mag':
            #print(newValue)
            newValue = list(newValue.split(","))
            if (newValue[1] == self.swtID):
                # print(newValue)
                self.__combinedNuelleData.combinedData[0] = float(
                    newValue[5])  #feld 6 xmag
                self.__combinedNuelleData.combinedData[1] = float(
                    newValue[6])  #feld 7 ymag
                self.__combinedNuelleData.combinedData[2] = float(
                    newValue[7])  #feld 8 zmag
                self.__combinedNuelleData.combinedData[3] = newValue[
                    4]  #timestamp
        elif ValueName == 'StringNodeId(ns=3;s="DB_OPC_UA"."IMS_5A_M0009682"."I_Eingaenge"."I_IMS5A_IL")':
            self.__combinedNuelleData.combinedData[5] = newValue
        elif ValueName == 'StringNodeId(ns=3;s="DB_OPC_UA"."IMS_5A_M0009682"."I_Eingaenge"."I_IMS5A_B4")':
            self.__combinedNuelleData.combinedData[6] = newValue
        else:
            # pass
            print("Warnung - Unbekannte Variable erhalten: " + newValue +
                  "    -     " + ValueName)

    def getDataSnapshot(self):
        return self.__combinedNuelleData.combinedData

    def __insertVariables(self):
        while not self.__stopFlag:
            if (not self.__valueQueue.empty()):
                queueContent = self.__valueQueue.get()
                self.__addToNuelleData(queueContent[0], queueContent[1])
                self.__valueQueue.task_done()

    def startCollectingData(self):
        for i in range(20):
            self.__insertVariablesThread = Thread(
                target=self.__insertVariables,
                args=(),
                name="insertVariables{0}".format(i))
            self.__insertVariablesThread.start()

    def stopCollectionData(self):
        self.__stopFlag = True
        self.__insertVariablesThread.join()

    def writeStation(self, address, value):
        self.OPCUA_write(address, value)

    def resetStation(self, number):
        for address in StationLightNode[number].values():
            self.OPCUA_write(address, False)
            print(address, "False")

    def endofProgramm(self):
        #        for LightDict in StationLightNode[1:]:
        #            self.OPCUA_write(LightDict['IDofGreen'], True)
        #            self.OPCUA_write(LightDict['IDofOrange'], False)
        #            self.OPCUA_write(LightDict['IDofRed'], False)
        # print("Writes Done")
        # time.sleep(2)
        self.stopCollectionData()
        print("Stoped Collecting")
        self.OPCUA_stopClient()
        print("Stoped OPCUA")
        self.MQTT_stopClient()
        print("Stoped MQTT")
        print("Stopped!")
class AgentOPCUA(Agent):
    """Defines an Agent communicating via OPCUA."""
    def __init__(self, hyperparams):
        """Initializes the agent.

        Args:
            hyperparams: Dictionary of hyperparameters.

        """
        Agent.__init__(self, hyperparams)
        self.x0 = None

        self.dt = self._hyperparams['dt']
        self.scaler = self._hyperparams['scaler']
        self.action_scaler = self._hyperparams['action_scaler']
        self.actuator_overrides = self._hyperparams['override_actuator']
        self.sensor_overrides = self._hyperparams['override_sensor']
        self.signals = self._hyperparams['send_signal']
        self.sensors = self._hyperparams['opc_ua_states_include']
        self.actuators = self.u_data_types
        self.client = None
        self.pool = ThreadPool(len(self.sensors))
        self.debug = False

    def __init_opcua(self):
        if self.client is not None:  # Close existing connection
            try:
                self.client.disconnect()
            except ua.uaerrors.UaError:
                pass
        self.client = Client(self._hyperparams['opc-ua_server'])
        self.client.connect()
        try:
            # Get Nodes
            self.opcua_vars = {}

            for sensor in (self.sensors + self.actuators):
                self.opcua_vars[sensor] = self.__get_node(sensor.value)
            for signal in self.signals:
                self.opcua_vars[signal['signal']] = self.__get_node(
                    signal['signal'])
        except Exception:  # Close connection in case of error
            self.close()
            raise

    def __get_node(self, sensor):
        browse_name = sensor.split(',')
        try:
            return self.client.get_objects_node().get_child(browse_name)
        except ua.uaerrors.BadNoMatch:
            logging.critical("Node not found: '%s'" % (sensor))
            raise

    def transform(self, sensor, sensor_data):
        """Scales sates according to the scaler."""
        data_idx = self._x_data_idx[sensor]
        return (sensor_data -
                self.scaler.mean_[data_idx]) / self.scaler.scale_[data_idx]

    def inverse_transform(self, actuator, actuator_data):
        """Inverse actions according to the scaler."""
        data_idx = self._u_data_idx[actuator]
        return actuator_data * self.action_scaler.scale_[
            data_idx] + self.action_scaler.mean_[data_idx]

    def read_sensor(self, sensor):
        """Reads an OPCUA sensor.

        Args:
            sensor: Sensor identifier (as specified in hyperparams file)

        Returns:
            sensor_data: Array of sensor readings.

        """
        sensor_data = self.opcua_vars[sensor].get_value()
        if np.isscalar(sensor_data):  # Wrap scalars into single element arrays
            sensor_data = [sensor_data]
        return self.transform(sensor, np.asarray(sensor_data))

    def write_actuator(self, actuator, data):
        """Sets an OPCUA actuator.

        Args:
            actuator: Actuator identifier (as specified in hyperparams file)
            data: Value to set the actuator to. Arrays of length one are unboxed to a scalar.

        """
        if len(data) == 1:
            data = data.item()
        data = ua.Variant(self.inverse_transform(actuator, data),
                          ua.VariantType.Float)
        try:
            self.opcua_vars[actuator].set_data_value(data)
        except ua.uaerrors._auto.BadTypeMismatch:
            logging.critical(
                "Failed to write %r to %r of type %r" %
                (data, actuator, self.opcua_vars[actuator].get_data_type()))
            raise

    def reset(self, cond):
        """Reset the agent for a particular experiment condition.

        Args:
            condition: An index into hyperparams['reset_conditions'].

        """
        if not self.debug:
            input('Press Enter to confirm reset')

    def sample(self,
               policy,
               condition,
               save=True,
               noisy=True,
               reset_cond=None,
               **kwargs):
        """Performs agent reset and rolls out given policy to collect a sample.

        Args:
            policy: A Policy object.
            condition: Which condition setup to run.
            save: Whether or not to store the trial into the samples.
            noisy: Whether or not to use noise during sampling.
            reset_cond: The initial condition to reset the agent into.

        Returns:
            sample: A Sample object.

        """
        # Get a new sample
        sample = Sample(self)
        sample_ok = False
        while not sample_ok:
            if not self.debug:
                self.reset(reset_cond)

            self.__init_opcua()

            if noisy:
                noise = generate_noise(self.T, self.dU, self._hyperparams)
            else:
                noise = None

            # Execute policy over a time period of [0,T]
            start = time.time()
            for t in range(self.T):
                # Read sensors and store sensor data in sample
                def store_sensor(sensor):
                    sample.set(sensor, self.read_sensor(sensor), t)

                self.pool.map(store_sensor, self.sensors)
                # Override sensors
                for override in self.sensor_overrides:
                    if override['condition'](t):
                        sensor = override['sensor']
                        sample.set(sensor, override['value'](sample, t), t)

                print('X_%02d' % t, sample.get_X(t))

                # Get action
                U_t = policy.act(sample.get_X(t), sample.get_obs(t), t, noise)

                # Override actuators
                for override in self.actuator_overrides:
                    if override['condition'](t):
                        actuator = override['actuator']
                        U_t[self._u_data_idx[actuator]] = np.copy(
                            override['value'])

                # Send signals
                self.send_signals(t)

                # Perform action
                for actuator in self._u_data_idx:
                    self.write_actuator(actuator,
                                        U_t[self._u_data_idx[actuator]])
                sample.set(ACTION, U_t, t)

                print('U_%02d' % t, U_t)

                # Check if agent is keeping up
                sleep_time = start + (t + 1) * self.dt - time.time()
                if sleep_time < 0:
                    logging.critical("Agent can't keep up. %fs behind." %
                                     sleep_time)
                elif sleep_time < self.dt / 2:
                    logging.warning(
                        "Agent may not keep up (%.0f percent busy)" %
                        (((self.dt - sleep_time) / self.dt) * 100))

                # Wait for next timestep
                if sleep_time > 0 and not self.debug:
                    time.sleep(sleep_time)
            if save:
                self._samples[condition].append(sample)
            self.finalize_sample()

            sample_ok = self.debug or input('Continue?') == 'y'
            if not sample_ok:
                print('Repeating')
        return sample

    def finalize_sample(self):
        """Adds additional waiting time to allow agent to reset. Sends final signals."""
        if not self.debug:
            time.sleep(10)
        self.send_signals(self.T)

    def send_signals(self, t):
        """Sends edge-controlled OPCUA signals."""
        if not self.debug:
            for signal in self.signals:
                if signal['condition'](t):
                    self.send_signal(signal, True)
                    thread.start_new_thread(self.send_signal,
                                            (signal, False, 2))

    def send_signal(self, signal, value, sleep=0):
        """Sends an edge-controlled OPCUA signal."""
        if sleep > 0:
            time.sleep(sleep)

        opcua_var = self.opcua_vars[signal['signal']]
        print("Signal", signal['signal'], value)
        opcua_var.set_data_value(ua.Variant(value, ua.VariantType.Boolean))

    def close(self):
        """Releases any resources the agent may hold."""
        if self.client is not None:
            self.client.disconnect()
Beispiel #32
0
class OpcClient():
    """A simplified OpClient.

    This is a opc client that can be leveraged to
    subscribe to the OPC data change notifications.

    You should interact with the client using
    * add_notification_handler
    * subscribe_variable
    * unsubscribe_variable

    So typically:
    ```
    # setup client
    cl = OpcClient(...)
    # define handler
    def handler(update):
        # data update : {'node': <node>, 'timestamp': <datetime>, 'value': <value>, 'data': <data>}
        # do something with update here
    # add handler
    cl.add_notification_handler(handler)
    # subscribe to variable
    cl.subscribe_variable(cl.get_node("ns=3;i=2002"))

    time.sleep(100)
    cl.disconnect()
    ```

    *Note*
    Make sure to call disconnect before shutting down in
    order to ensure a clean close.

    See: https://github.com/FreeOpcUa/python-opcua

    Attributes
    ----------
    _address : str
        The connection string address
    _address_obfuscated : str
        The connection string address obfuscating a potnetial password
    _client : OPCLibClient
        The opc lib client
    _subscription : ua.Subscription
        The ua subscription handle that can be used
        to create new subscritions or unsubscribe
    _sub_handles : dict
        A dictionary mapping ua.Node variables to
        subscription handles to be able to unsubscribe
        from them again
    _handlers : list
        A list of handler functions
    """
    def __init__(self, host, port, path='/', username=None, password=None):
        """Create a new OpClient.

        This will create a new opc client that can be
        leveraged to subscribe to the OPC data change
        notifications.

        Parameters
        ----------
        host : str
            The host name of the opc server.
        port : int
            The port of the opc server.
        path : str
            The path to add to the server as base
        username : str|None
            A username to use for authorization.
        password : str|None
            A password to use for authorization.
        """

        self._client = None
        self._subscription = None
        self._sub_handles = {}
        self._handlers = []

        # setup authorization
        auth = ''
        if username is not None:
            auth = '{}:{}@'.format(username, password)

        # define address
        self._address = self._address_obfuscated = "opc.tcp://{}{}:{}{}".format(auth, host, port, path)
        if username is not None and password is not None:
            self._address_obfuscated = self._address.replace(password, '***')

        Logger.trace('Created OpcClient', fields={
            'address': self._address_obfuscated
        })

        # setup client
        self.init_client()
        # setup subscriptions
        self.init_subscriptions()

    def init_client(self):
        """Initialize the client.

        This will connect to the client using
        the address. This is required to be
        called before anything else interacting
        with the opc server is done.
        """
        try:
            self._client = OPCLibClient(self._address)
            self._client.connect()
            self._client.load_type_definitions()
            self.namespace = self._client.get_namespace_array()
            Logger.trace('Connection established')
        except Exception as e:
            Logger.error('Failed connecting to address "{}"'.format(self._address_obfuscated))
            Logger.error('{}'.format(e))
            raise e

    def log_info(self):
        root = self._client.get_root_node()
        objects = self._client.get_objects_node()
        children = root.get_children()
        # print '{}:{}'.format(namespace[children[1].nodeid.NamespaceIndex], children[1].nodeid.Identifier)
        # print self._client.get_node("ns=0;i=86")
        Logger.debug("Retrieved Client Info", fields={
            'root': root,
            'objects': objects,
            'children': children,
            'namespace': self.namespace
        })

    def full_uri(self, node):
        """Resolve the full uri of a ua.Node.

        Parameters
        ----------
        node : ua.Node
            A node from the OPC interface.

        Returns
        -------
        str :
            The namespace prefixed full uri of the entity.
        """
        return '{}:{}'.format(
            self.namespace[node.nodeid.NamespaceIndex], node.nodeid.Identifier)

    def get_by_uri(self, uri):
        """Resolve the full uri to a ua.Node.

        Parameters
        ----------
        uri : str
            The uri to the ua.Node.

        Returns
        -------
        ua.Node :
            The resolved node.
        """
        ns_match = None
        for ns in self.namespace:
            if '{}:'.format(ns) in uri:
                ns_match = ns
                break
        if ns_match is None:
            raise RuntimeError('Namespace of "{}" not available'.format(uri))
        ns_idx = self._client.get_namespace_index(ns_match)
        identifier = uri.replace('{}:'.format(ns_match), '')
        try:
            int(identifier)
            is_int = True
        except:
            is_int = False

        substituted = 'ns={};{}={}'.format(ns_idx, 'i' if is_int else 's', identifier)
        return self._client.get_node(substituted)

    def init_subscriptions(self):
        """Initialize the subscriptions.

        This will initialize a subscription handler
        and afterwards will be ready to subscribe to
        specific variables.
        """
        if self._client is None:
            raise RuntimeError('Client not initialized yet.')

        self._subscription = self._client.create_subscription(500, self)
        Logger.trace('Base Subscription established')

    def subscribe_variable(self, variable):
        """Subscribe to a OPC variable.

        This will subscribe the client to
        the given variable and any data change
        notification will be published.

        Parameters
        ----------
        variable : ua.Node
            The ua node, e.g. client.get_node(ua.NodeId(1002, 2)) or
            client.get_node("ns=3;i=2002")
        """
        if self._subscription is None:
            raise RuntimeError('Subscriptions not initialized yet.')

        if variable in self._sub_handles.keys():
            Logger.info('Already subscribed to "{}"'.format(variable))
            return
        self._sub_handles[variable] = self._subscription.subscribe_data_change(variable)

    def unsubscribe_variable(self, variable):
        """Unsubscribe from a OPC variable.

        This will unsubscribe the client from
        the given variable.

        Parameters
        ----------
        variable : ua.Node
            The ua node, e.g. client.get_node(ua.NodeId(1002, 2)) or
            client.get_node("ns=3;i=2002")
        """
        if self._subscription is None:
            raise RuntimeError('Subscriptions not initialized yet.')

        if variable not in self._sub_handles.keys():
            Logger.info('Not subscribed to "{}"'.format(variable))
            return
        self._subscription.unsubscribe(self._sub_handles[variable])
        del self._sub_handles[variable]

    def disconnect(self):
        """Disconnect the client.
        """
        if self._client is None:
            return
        try:
            self._client.disconnect()
        except Exception:
            pass

    def datachange_notification(self, node, value, data):
        """Receiver from the OPC client.

        This gets called by OPC client on subscription
        notification.

        Parameter
        ---------
        node : ua.Node
            The node from which we received the data.
        value : any
            The value notification
        data : any
            The data of the notification
        """
        timestamp = datetime.now()
        if hasattr(data, 'MonitoredItemNotification') and \
                hasattr(data.MonitoredItemNotification, 'SourceTimestamp'):
            timestamp = data.MonitoredItemNotification.SourceTimestamp
        Logger.debug('OpcClient: Received data change notification', fields={
            'node': node,
            'value': value,
            'data': data,
            'timestamp': timestamp.isoformat()
        })
        # send update to handlers
        update = {
            'node': node,
            'value': value,
            'data': data,
            'timestamp': timestamp
        }
        for hdl in self._handlers:
            hdl(update)


    def add_notification_handler(self, handler):
        """Add a handler function.

        This handler `def handler(update)` will be
        called upon reception of a notification from
        the OPC Client. The update will have the
        following data:
        ```{
            'node': <node>,
            'value': <value>,
            'data': <data>,
            'timestamp': <timestamp>
        }```
        """
        self._handlers.append(handler)
Beispiel #33
0
class Cliente():
    def __init__(self, direccion, suscribir_eventos, SubHandler):
        self.direccion = direccion
        self.client = Client(direccion)
        self.alturas = {'H1': 0, 'H2': 0, 'H3': 0, 'H4': 0}
        self.temperaturas = {'T1': 0, 'T2': 0, 'T3': 0, 'T4': 0}
        self.valvulas = {'valvula1': 0, 'valvula2': 0}
        self.razones = {'razon1': 0, 'razon2': 0}
        self.subscribir_eventos = suscribir_eventos
        self.periodo = 100  # cantidad de milisegundos para revisar las variables subscritas
        self.SubHandlerClass = SubHandler

    def Instanciacion(self):
        self.root = self.client.get_root_node()
        self.objects = self.client.get_objects_node()
        self.Tanques = self.objects.get_child(
            ['2:Proceso_Tanques', '2:Tanques'])
        self.Valvulas = self.objects.get_child(
            ['2:Proceso_Tanques', '2:Valvulas'])
        self.Razones = self.objects.get_child(
            ['2:Proceso_Tanques', '2:Razones'])

        # Obtención de las alturas
        self.alturas['H1'] = self.Tanques.get_child(['2:Tanque1', '2:h'])
        self.alturas['H2'] = self.Tanques.get_child(['2:Tanque2', '2:h'])
        self.alturas['H3'] = self.Tanques.get_child(['2:Tanque3', '2:h'])
        self.alturas['H4'] = self.Tanques.get_child(['2:Tanque4', '2:h'])

        # Obtención de los pumps
        self.valvulas['valvula1'] = self.Valvulas.get_child(
            ['2:Valvula1', '2:u'])
        self.valvulas['valvula2'] = self.Valvulas.get_child(
            ['2:Valvula2', '2:u'])

        # Obtención de los switches
        self.razones['razon1'] = self.Razones.get_child(
            ['2:Razon1', '2:gamma'])
        self.razones['razon2'] = self.Razones.get_child(
            ['2:Razon2', '2:gamma'])

        # Evento (alarma en este caso)
        if self.subscribir_eventos:
            self.myevent = self.root.get_child([
                "0:Types", "0:EventTypes", "0:BaseEventType", "2:Alarma_nivel"
            ])  # Tipo de evento
            self.obj_event = self.objects.get_child(
                ['2:Proceso_Tanques', '2:Alarmas',
                 '2:Alarma_nivel'])  # Objeto Evento
            self.handler_event = self.SubHandlerClass()
            self.sub_event = self.client.create_subscription(
                self.periodo, self.handler_event)  # Subscripción al evento
            self.handle_event = self.sub_event.subscribe_events(
                self.obj_event, self.myevent)

    def subscribir_cv(self):  # Subscripción a las variables controladas
        self.handler_cv = self.SubHandlerClass()
        self.sub_cv = self.client.create_subscription(self.periodo,
                                                      self.handler_cv)
        for key, var in self.alturas.items():
            self.sub_cv.subscribe_data_change(var)
        for key, var in self.temperaturas.items():
            self.sub_cv.subscribe_data_change(var)

    def subscribir_mv(self):  # Subscripación a las variables manipuladas
        self.handler_mv = self.SubHandlerClass()
        self.sub_mv = self.client.create_subscription(self.periodo,
                                                      self.handler_mv)
        for key, var in self.valvulas.items():
            self.sub_mv.subscribe_data_change(var)
        for key, var in self.razones.items():
            self.sub_mv.subscribe_data_change(var)

    def conectar(self):
        try:
            self.client.connect()
            self.objects = self.client.get_objects_node()
            # print('Cliente OPCUA se ha conectado')
            self.Instanciacion()

        except:
            self.client.disconnect()
            print('Cliente no se ha podido conectar')
Beispiel #34
0
class omronNx:
    def __init__(self, config_json, qt_main_ui, time_update):
        self._qt_main_ui    = qt_main_ui
        self._config_json   = config_json
        self.time_update    = time_update
        self.PLC            = plc.PLC(config_json, qt_main_ui, self)
        self.connect_addres = None
        self.opc_ua_client  = None
        self.Time           = 0
        self.F              = 20
        self.Drivers        = MPoll.MotorsPoll(config_json, qt_main_ui, self)

        self.is_stop  = False
        self.is_opcua_connected = False

        self.is_started_drivers = False
        self.read_config()
        self.create_opc_client()
        self.init_ui_signals()

        self.count_update = 0
        

    def init_ui_signals(self):
        self._qt_main_ui.ConnectToOmronBtn.clicked.connect(self.connect)
        
    def create_opc_client(self):
        self.opc_ua_client  = Client(
            self.connect_addres
        )
    def connect(self):
        try:
            self.opc_ua_client.connect()
            self.add_to_log_box("connect to : {}".format(self.connect_addres))
            self.is_opcua_connected = True
        except Exception as e:
            self.is_opcua_connected = True
            self.add_to_log_box("connection error : {}".format(str(e)))
            #self.PLC._set_alarm_on();

        

    def update(self):
        self.Drivers.update()
        self.view_update()
        self.PLC.update()
       

        pass

    def view_update(self):
        self._qt_main_ui.ferq_lab.display(self.F)
        pass


    def read_config(self):
        try:
            self.connect_addres = self._config_json["network"][0]["opc_addr"]
        except Exception as e:
            self.add_to_log_box(str(e))


    def get_value(self, cmd):
        pass

    def set_value(self, node, value):
        try :
            node = self.opc_ua_client.get_node(node)
            node.set_attribute(ua.AttributeIds.Value, ua.DataValue(value))
        except Exception as e:
            self.add_to_log_box("set_value error : {}".format(str(e)))
        pass

    def add_to_log_box(self, text):
        tmp_text =  "" #self._qt_main_ui.log_box.text
        self._qt_main_ui.log_box.setText(tmp_text + "\n" +text)
        pass
Beispiel #35
0
class ScheduleCTRLWORD(object):
    """
    RuleBasic定义
    """
    def __init__(self, AName):
        '''
        :param tagID: 要采集的变量名称
        :param src: 数据源,为dict类型
        '''
        self._redispool = redis.ConnectionPool(
            host=constant.REDIS_HOST, password=constant.REDIS_PASSWORD)
        self._name = AName
        self._ls1ctrlword = 0
        self._lq1pv = 40
        self._ld1pv = 50
        self._ls2ctrlword = 0
        self._lq2pv = 49
        self._ld2pv = 40
        self._kt1pv = 30
        self._kt2pv = 30
        self._kt1vopen = 50
        self._kt2vopen = 50
        self._ls1_run = 0
        self._ls1_stop = 0
        self._lqt1_run = 0
        self._lqt1_stop = 0
        self._ld1_run = 0
        self._ld1_stop = 0
        self._ls2_run = 0
        self._ls2_stop = 0
        self._lqt2_run = 0
        self._lqt2_stop = 0
        self._ld2_run = 0
        self._ld2_stop = 0
        self._ls1_wd = 10
        self._ls2_wd = 10
        self._ls1_net = 1
        self._ls2_net = 1
        self._connected = False
        self._client = None
        self._nodels1 = None
        self._nodeld1pv = None
        self._nodelq1pv = None
        self._nodels2 = None
        self._nodeld2pv = None
        self._nodelq2pv = None
        self._nodekt1pv = None
        self._nodekt2pv = None
        self._nodekt1vpv = None
        self._nodekt2vpv = None
        # self.INI_CTRL_WORD()

    def INI_CTRL_WORD(self):
        # client = Client('opc.tcp://127.0.0.1:49320')
        self.connect()
        # self._nodels1 = self._client.get_node('ns = 2;s = SCADA.DO.TSET1')
        #         # self._nodeld1pv = self._client.get_node('ns = 2;s = SCADA.DO.LD1SET')
        #         # self._nodelq1pv = self._client.get_node('ns = 2;s = SCADA.DO.LQ1SET')
        #         # self._nodels2 = self._client.get_node('ns = 2;s = SCADA.DO.TSET2')
        #         # self._nodeld2pv = self._client.get_node('ns = 2;s = SCADA.DO.LD2SET')
        #         # self._nodelq2pv = self._client.get_node('ns = 2;s = SCADA.DO.LQ2SET')
        #         # self._nodekt1pv = self._client.get_node('ns = 2;s = SCADA.DO.KT1SET')
        #         # self._nodekt2pv = self._client.get_node('ns = 2;s = SCADA.DO.KT2SET')
        #         # self._nodekt1vpv = self._client.get_node('ns = 2;s = SCADA.DO.SDF1SET')
        #         # self._nodekt2vpv = self._client.get_node('ns = 2;s = SCADA.DO.SDF2SET')
        self._nodels1 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.KG2_KG1_Lighting.H_P_Man_Ang_x.H_P_Man_Ang_038'
        )
        self._nodeld1pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_2')
        self._nodelq1pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_0')
        self._nodels2 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.KG2_KG1_Lighting.H_P_Man_Ang_x.H_P_Man_Ang_039'
        )
        self._nodeld2pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_3')
        self._nodelq2pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_1')
        self._nodek1p1 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_28')
        self._nodek2p2 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_35')
        self._nodek3p3 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_42')
        self._nodek4p4 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_49')
        self._nodek5p5 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_56')

    def Write_LS1_CTRLWord(self):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            ls1ctrl = self.GetCtrlWord(self._ls1_wd, self._ls1_run,
                                       self._ls1_stop, self._ld1_run,
                                       self._ld1_stop, self._lqt1_run,
                                       self._lqt1_stop)
            self._nodels1.set_value(
                ua.DataValue(ua.Variant(ls1ctrl, ua.VariantType.Int16)))
        except Exception as err:
            print(err)
            pass

    def Equip_LS1Control(self, AEquip, AType):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            self._ls1_run = 0
            self._ls1_stop = 0
            self._ld1_run = 0
            self._ld1_stop = 0
            self._lqt1_run = 0
            self._lqt1_stop = 0
            if ((AEquip == "LS1") and (AType == "RUN")):
                self._ls1_run = 1
            elif ((AEquip == "LS1") and (AType == "STOP")):
                self._ls1_stop = 1
            elif ((AEquip == "LD1") and (AType == "RUN")):
                self._ld1_run = 1
            elif ((AEquip == "LD1") and (AType == "STOP")):
                self._ld1_stop = 1
            elif ((AEquip == "LQT1") and (AType == "RUN")):
                self._lqt1_run = 1
            elif ((AEquip == "LQT1") and (AType == "STOP")):
                self._lqt1_stop = 1
            ls1ctrl = self.GetCtrlWord(int(100), self._ls1_run, self._ls1_stop,
                                       self._ld1_run, self._ld1_stop,
                                       self._lqt1_run, self._lqt1_stop)
            self._nodels1.set_value(
                ua.DataValue(ua.Variant(ls1ctrl, ua.VariantType.Int16)))
        except Exception as err:
            print(err)
            pass

    def Write_LS1_Params(self, AEquipment, AValue):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            if (AEquipment == "LD1"):
                self._ld1pv = int(AValue)
                self._nodeld1pv.set_value(
                    ua.DataValue(
                        ua.Variant(10 * int(self._ld1pv),
                                   ua.VariantType.UInt16)))
            elif (AEquipment == "LQ1"):
                self._lq1pv = int(AValue)
                self._nodelq1pv.set_value(
                    ua.DataValue(
                        ua.Variant(10 * int(self._lq1pv),
                                   ua.VariantType.UInt16)))
            # self._nodekt1pv.set_value(ua.DataValue(ua.Variant(10*int(self._kt1pv),ua.VariantType.UInt16)))
            # self._nodekt2pv.set_value(ua.DataValue(ua.Variant(10*int(self._kt2pv),ua.VariantType.UInt16)))
            # self._nodekt1vpv.set_value(ua.DataValue(ua.Variant(10*int(self._kt1vopen),ua.VariantType.UInt16)))
            # self._nodekt2vpv.set_value(ua.DataValue(ua.Variant(10*int(self._kt2vopen),ua.VariantType.UInt16)))
        except Exception as err:
            print(err)
            pass

    def Equip_LS2Control(self, AEquip, AType):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            self._ls2_run = 0
            self._ls2_stop = 0
            self._ld2_run = 0
            self._ld2_stop = 0
            self._lqt2_run = 0
            self._lqt2_stop = 0
            if ((AEquip == "LS2") and (AType == "RUN")):
                self._ls2_run = 1
            elif ((AEquip == "LS2") and (AType == "STOP")):
                self._ls2_stop = 1
            elif ((AEquip == "LD2") and (AType == "RUN")):
                self._ld2_run = 1
            elif ((AEquip == "LD2") and (AType == "STOP")):
                self._ld2_stop = 1
            elif ((AEquip == "LQT2") and (AType == "RUN")):
                self._lqt2_run = 1
            elif ((AEquip == "LQT2") and (AType == "STOP")):
                self._lqt2_stop = 1
            ls2ctrl = self.GetCtrlWord(int(100), self._ls2_run, self._ls2_stop,
                                       self._ld2_run, self._ld2_stop,
                                       self._lqt2_run, self._lqt2_stop)
            self._nodels2.set_value(
                ua.DataValue(ua.Variant(ls2ctrl, ua.VariantType.Int16)))
        except Exception as err:
            print(err)
            pass

    def Write_LS2_Params(self, AEquipment, AValue):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            if (AEquipment == "LD2"):
                self._ld2pv = int(AValue)
                self._nodeld2pv.set_value(
                    ua.DataValue(
                        ua.Variant(10 * int(self._ld2pv),
                                   ua.VariantType.Int16)))
            elif (AEquipment == "LQ2"):
                self._lq2pv = int(AValue)
                self._nodelq2pv.set_value(
                    ua.DataValue(
                        ua.Variant(10 * int(self._lq2pv),
                                   ua.VariantType.Int16)))
            # self._nodekt1pv.set_value(ua.DataValue(ua.Variant(10*int(self._kt1pv),ua.VariantType.UInt16)))
            # self._nodekt2pv.set_value(ua.DataValue(ua.Variant(10*int(self._kt2pv),ua.VariantType.UInt16)))
            # self._nodekt2vpv.set_value(ua.DataValue(ua.Variant(10*int(self._kt2vopen),ua.VariantType.UInt16)))
            # self._nodekt1vpv.set_value(ua.DataValue(ua.Variant(10*int(self._kt1vopen),ua.VariantType.UInt16)))
        except Exception as err:
            print(err)
            pass

    def connect(self):
        self.disconnect()
        self._client = Client('opc.tcp://127.0.0.1:49320')
        self._client.connect()
        # self._nodels1 = self._client.get_node('ns = 2;s = SCADA.DO.TSET1')
        # self._nodeld1pv = self._client.get_node('ns = 2;s = SCADA.DO.LD1SET')
        # self._nodelq1pv = self._client.get_node('ns = 2;s = SCADA.DO.LQ1SET')
        # self._nodels2 = self._client.get_node('ns = 2;s = SCADA.DO.TSET2')
        # self._nodeld2pv = self._client.get_node('ns = 2;s = SCADA.DO.LD2SET')
        # self._nodelq2pv = self._client.get_node('ns = 2;s = SCADA.DO.LQ2SET')
        # self._nodekt1pv = self._client.get_node('ns = 2;s = SCADA.DO.KT1SET')
        # self._nodekt2pv = self._client.get_node('ns = 2;s = SCADA.DO.KT2SET')
        # self._nodekt1vpv = self._client.get_node('ns = 2;s = SCADA.DO.SDF1SET')
        # self._nodekt2vpv = self._client.get_node('ns = 2;s = SCADA.DO.SDF2SET')
        self._nodels1 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.KG2_KG1_Lighting.H_P_Man_Ang_x.H_P_Man_Ang_038'
        )
        self._nodeld1pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_2')
        self._nodelq1pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_0')
        self._nodels2 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.KG2_KG1_Lighting.H_P_Man_Ang_x.H_P_Man_Ang_039'
        )
        self._nodeld2pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_3')
        self._nodelq2pv = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.JN_x.JN_1')
        self._nodek1p1 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_28')
        self._nodek2p2 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_35')
        self._nodek3p3 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_42')
        self._nodek4p4 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_49')
        self._nodek5p5 = self._client.get_node(
            'ns = 2;s = PLC.KG1.Global.H_P_Pid_Set_X.H_P_Pid_Set_56')
        self._connected = True

    def disconnect(self):
        if self._connected:
            print("Disconnecting from server")
            self._connected = False
            try:
                self._client.disconnect()
            finally:
                self._reset()

    def _reset(self):
        self.client = None
        self._connected = False

    def Write_LS2_CTRLWord(self):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            ls2ctrl = self.GetCtrlWord(self._ls2_wd, self._ls2_run,
                                       self._ls2_stop, self._ld2_run,
                                       self._ld2_stop, self._lqt2_run,
                                       self._lqt2_stop)
            # self._nodels2 = self._client.get_node('ns = 2;s = SCADA.DO.TSET2')
            self._nodels2.set_value(
                ua.DataValue(ua.Variant(ls2ctrl, ua.VariantType.Int16)))
        except Exception as err:
            print(err)
            pass

    def GetCtrlWord(self, AOutTemp, ALSRun, ALSSTOP, ALDRun, ALDSTOP,
                    ALQT_T1_RUN, ALQT_T1_STOP):
        if int(AOutTemp) > 30:
            int_num = int(AOutTemp)
        else:
            int_num = int(AOutTemp)
        bin_num = bin(int_num)
        slow = str(bin_num)[2:]
        if len(slow) == 1:
            slow = '0000000' + slow
        elif len(slow) == 2:
            slow = '000000' + slow
        elif len(slow) == 3:
            slow = '00000' + slow
        elif len(slow) == 4:
            slow = '0000' + slow
        elif len(slow) == 5:
            slow = '000' + slow
        elif len(slow) == 6:
            slow = '00' + slow
        elif len(slow) == 7:
            slow = '0' + slow

        shigh = ''
        # 第8位
        if ALSRun == 1:
            shigh = '01'
        # 第9位
        elif ALSSTOP == 1:
            shigh = '10'
        elif (ALSRun == 0) and (ALSSTOP == 0):
            shigh = '00'

        if ALDRun == 1:
            shigh = "01" + shigh
        elif ALDSTOP == 1:
            shigh = '10' + shigh
        elif (ALDRun == 0) and (ALDSTOP == 0):
            shigh = '00' + shigh
            # 第12位
        if ALQT_T1_RUN == 1:
            shigh = '01' + shigh
        elif ALQT_T1_STOP == 1:
            shigh = '10' + shigh
        elif (ALQT_T1_RUN == 0) and (ALQT_T1_RUN == 0):
            shigh = '00' + shigh

        shigh = '00' + shigh
        print("字符串" + shigh + slow + ":整型:" + str(int(shigh + slow, 2)))
        return int(shigh + slow, 2)

    def Write_LS_INIWORD(self, AEquip, AWD):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            lsctrl = self.GetCtrlWord(int(AWD), 0, 0, 0, 0, 0, 0)
            if AEquip == "LS1":
                # self._nodels1 = self._client.get_node('ns = 2;s = SCADA.DO.TSET1')
                self._nodels1.set_value(
                    ua.DataValue(ua.Variant(lsctrl, ua.VariantType.Int16)))
            elif AEquip == "LS2":
                # self._nodels2 = self._client.get_node('ns = 2;s = SCADA.DO.TSET2')
                self._nodels2.set_value(
                    ua.DataValue(ua.Variant(lsctrl, ua.VariantType.Int16)))
        except Exception as err:
            print(err)
            pass

    def GetFaultCtrlWord(self, AOutTemp, AFault):
        if int(AOutTemp) > 30:
            int_num = int(AOutTemp)
        else:
            int_num = int(AOutTemp)
        bin_num = bin(int_num)
        slow = str(bin_num)[2:]
        if len(slow) == 1:
            slow = '0000000' + slow
        elif len(slow) == 2:
            slow = '000000' + slow
        elif len(slow) == 3:
            slow = '00000' + slow
        elif len(slow) == 4:
            slow = '0000' + slow
        elif len(slow) == 5:
            slow = '000' + slow
        elif len(slow) == 6:
            slow = '00' + slow
        elif len(slow) == 7:
            slow = '0' + slow

        shigh = '000000'

        if AFault == 1:
            shigh = '1' + shigh
        else:
            shigh = '0' + shigh

        print("字符串" + shigh + slow + ":整型:" + str(int(shigh + slow, 2)))
        return int(shigh + slow, 2)

    def Write_LS_FaultReset(self, AEquipment):
        # client = Client('opc.tcp://127.0.0.1:49320')
        try:
            self.connect()
            if (AEquipment == "LS1"):
                lsctrl = self.GetFaultCtrlWord(100, 1)
                self._nodels1.set_value(
                    ua.DataValue(ua.Variant(int(lsctrl),
                                            ua.VariantType.Int16)))
                time.sleep(5)
                lsctrl = self.GetFaultCtrlWord(100, 0)
                self._nodels1.set_value(
                    ua.DataValue(ua.Variant(int(lsctrl),
                                            ua.VariantType.Int16)))
            elif (AEquipment == "LS2"):
                lsctrl = self.GetFaultCtrlWord(100, 1)
                self._nodels2.set_value(
                    ua.DataValue(ua.Variant(int(lsctrl),
                                            ua.VariantType.UInt16)))
                time.sleep(5)
                lsctrl = self.GetFaultCtrlWord(100, 0)
                self._nodels2.set_value(
                    ua.DataValue(ua.Variant(int(lsctrl),
                                            ua.VariantType.UInt16)))
        except Exception as err:
            print(err)
            pass
Beispiel #36
0
# encoding=utf-8

import sys, time

sys.path.insert(0, "..")
from opcua import Client

if __name__ == "__main__":

    # client = Client("opc.tcp://127.0.0.1:4840")
    # client = Client("opc.tcp://127.0.0.1:4840/freeopcua/server/")
    client = Client("opc.tcp://127.0.0.1:7766")  #connect using a user
    try:
        res = client.connect()

        # Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
        root = client.get_root_node()
        print("Objects node is: ", root)
        children = root.get_children()

        # Node objects have methods to read and write node attributes as well as browse or populate address space
        print("Children of root are: ", root.get_children())

        # get a specific node knowing its node id
        # var = client.get_node(ua.NodeId(1002, 2))
        # var = client.get_node("ns=3;i=2002")
        # print(var)
        # var.get_data_value() # get value of node as a DataValue object
        # var.get_value() # get value of node as a python builtin
        # var.set_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type
        # var.set_value(3.9) # set node value using implicit data type
def config_setup():

    data = {}
    configdict = dict()

    # OPC UA Initialisation
    while True:
        opcdata = GUI.opc_initialise()
        a = list()
        for num, val in opcdata.items():
            a.append(val)

        OPCname = str(a[0])
        OPCurl = str(a[1])

        client = Client(OPCurl)
        try:

            # Authentication requires copy of certificate and private key in local system.
            # need to add full path of private key and certificate file as parameters (not available at the moment)
            # client.set_security_string(security_algorithm , authentication_mode , path_of_certificate , path_of_private_key)) -> syntax
            # client.set_security_string("Basic256Sha256,SignAndEncrypt,server_cert.der,server_key.pem")  # need to add cert and key path

            client.connect()
            opclist.append(client)
            DB.get_opc(client)

            GUI.opc_pop()

            configdict.update({"OPC Server Name": OPCname})
            configdict.update({"OPC Server URL": OPCurl})
            break

        except:
            # Connecting to OPC UA Server without authentication
            try:
                client.connect()
                opclist.append(client)
                DB.get_opc(client)

                GUI.opc_pop()

                configdict.update({"OPC Server Name": OPCname})
                configdict.update({"OPC Server URL": OPCurl})
                break

            except:
                GUI.opc_error()

    # MySQL Initialisation

    while True:
        sqldata = GUI.sql_initialise()
        a = list()
        for num, val in sqldata.items():
            a.append(val)

        sqlhost = str(a[0])
        sqluser = str(a[1])
        sqlpwd = str(a[2])
        dbname = str(a[3])

        try:
            mydb = mysql.connector.connect(host=sqlhost,
                                           user=sqluser,
                                           passwd=sqlpwd,
                                           database=dbname)
            mycursor = mydb.cursor()
            GUI.sql_pop1()

            configdict.update({"SQL Host": sqlhost})
            configdict.update({"SQL Username": sqluser})
            configdict.update({"SQL Password": sqlpwd})
            configdict.update({"Database Name": dbname})

            DB.get_db(mydb)
            MYSQL_list.append(mydb)

            break

        except:
            try:
                mydb = mysql.connector.connect(host=sqlhost,
                                               user=sqluser,
                                               passwd=sqlpwd)
                mycursor = mydb.cursor()
                db = "CREATE DATABASE " + dbname
                db = str(db)
                mycursor.execute(db)

                mydb = mysql.connector.connect(host=sqlhost,
                                               user=sqluser,
                                               passwd=sqlpwd,
                                               database=dbname)
                mycursor = mydb.cursor()
                GUI.sql_pop2()

                configdict.update({"SQL Host": sqlhost})
                configdict.update({"SQL Username": sqluser})
                configdict.update({"SQL Password": sqlpwd})
                configdict.update({"Database Name": dbname})

                DB.get_db(mydb)
                MYSQL_list.append(mydb)
                break

            except:
                GUI.sql_error()

    # Mainflux API initialization
    while True:

        mainflux_data = GUI.flux_initialise()
        a = list()
        for num, val in mainflux_data.items():
            a.append(val)

        flux_ip = str(a[0])
        flux_port = str(a[1])
        flux_email = str(a[2])
        flux_pwd = str(a[3])

        try:
            token = DB.get_token(flux_ip, flux_port, flux_email, flux_pwd)

            GUI.flux_pop()

            configdict.update({"Mainflux IP": flux_ip})
            configdict.update({"Mainflux Port": flux_port})
            configdict.update({"Mainflux Email": flux_email})
            configdict.update({"Mainflux Password": flux_pwd})
            break

        except:
            GUI.flux_error()

    data['Settings'] = []
    data['Settings'].append(configdict)

    dir_path = os.path.dirname(os.path.realpath(__file__))
    dir_path = str(dir_path)
    configpath = dir_path + "\config.json"
    configpath = str(configpath)

    with open(configpath, 'w') as f:
        json.dump(data, f, indent=4)
Beispiel #38
0
 def test_get_endpointr(self):
     client = Client("opc.tcp://" + os.environ['TEST_IP'] + ":" + os.environ['TEST_PORT'])
     client.connect()
     endpoints = client.get_endpoints()
     self.assertEqual(len(endpoints), 4)
     client.disconnect()
Beispiel #39
0
class OpcProtocol():
    '''
    OPC Protocol settings
    '''
    def string_to_node_type(self, type='string'):
        if type == 'string':
            return ua.NodeIdType.String
        elif type == 'numeric':
            return ua.NodeIdType.Numeric
        else:
            return ua.NodeIdType.ByteString

    def __del__(self):
        self.Disconnect()

    def __init__(self, server_name):
        self.server_name = server_name

        namespaces = VAR.OPC_SERVERS[server_name]["namespaces"]

        # Get OPC UA node type
        for namespace in namespaces.keys():
            nodes = VAR.OPC_SERVERS[server_name]["namespaces"][namespace]["nodes"]
            for node in nodes:
                type = nodes[node]["opc_type"]
                nodes[node]["opc_type"] = self.string_to_node_type(type)

        self.Connect()

    def Connect(self):
        '''
        For creating connection to OPC UA Server
        '''
        server = VAR.OPC_SERVERS[self.server_name]["opc_server"]
        namespaces = VAR.OPC_SERVERS[self.server_name]["namespaces"]
        
        self.client = Client(server)
        try:
            self.client.connect()
            
            for namespace in namespaces.keys():
                VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["index"] = self.client.get_namespace_index(namespace)

        except Exception as e:
            print('Connect error:', e)
        finally:
            self.firstrun()


    def remove_subscribe(self):
        namespaces = VAR.OPC_SERVERS[self.server_name]["namespaces"]
        for namespace in namespaces.keys():
            nodes = VAR.OPC_SERVERS[self.server_name]['namespaces'][namespace]["nodes"]
            for node in nodes.keys():
                VAR.OPC_SERVERS[self.server_name]['namespaces'][namespace]["nodes"][node]["subscribe"].unsubscribe(
                    VAR.OPC_SERVERS[self.server_name]['namespaces'][namespace]["nodes"][node]["handler"]
                )
                VAR.OPC_SERVERS[self.server_name]['namespaces'][namespace]["nodes"][node]["subscribe"].delete()
        return True


    def Disconnect(self):
        '''
        Disconnect from OPC UA Server
        '''
        try:
            self.remove_subscribe()
            self.client.disconnect()
        except Exception as e:
            print('Disconnect error:', e)
        return "disconnect done"

    def create_node(self, node, namespace, type):
        return ua.NodeId(identifier=node, namespaceidx=namespace, nodeidtype=type)

    def firstrun(self):
        '''
        When OPC UA Server connection has been established, do this once
        '''
        try:
            if VAR.FIRST_RUN:
                namespaces = VAR.OPC_SERVERS[self.server_name]["namespaces"]

                for namespace in namespaces.keys():
                    index = VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["index"]
                    nodes = VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"]
                    for node in nodes.keys():
                        type = VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["opc_type"]
                        nodeid = self.create_node(node, index, type)
                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["opc_nodeid"] = nodeid

                        this_node = self.client.get_node(nodeid)
                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["opc_variable"] = this_node

                        value = this_node.get_value()

                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["value"] = value
                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["timestamp"] = str(datetime.datetime.utcnow())

                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["handler"] = NodeHandler(self.server_name, namespace)
                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["subscribe"] = self.client.create_subscription(
                            100,
                            VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["handler"]
                        )
                        VAR.OPC_SERVERS[self.server_name]["namespaces"][namespace]["nodes"][node]["subscribe"].subscribe_data_change(this_node)
        except Exception as e:
            print('firstRun error:', e)
        finally:
            VAR.FIRST_RUN = False

    def reset(self):
        self.remove_subscribe()
        VAR.FIRST_RUN = True
        self.firstrun()
Beispiel #40
0
class PluginConsoleTool(cmd.Cmd):
    intro = '''
Welcome to the (opcua plugin tool) shell.
Type help or ? to list commands.\n
'''
    prompt = '(opcua plugin tool) > '

    def __init__(self):
        super(PluginConsoleTool, self).__init__()
        self.server_uri = "opc.tcp://localhost:4840"
        self.opcua = None
        self.node = None

    def do_plugin_list(self, arg):
        try:
            code, data = self.node.call_method('2:get_plugin_list')
            if code == '0':
                result = json.loads(data)
                if result['Error']:
                    print(result['Error'])
                else:
                    print(result['Success'])
            else:
                print(code, data)
        except Exception as e:
            print(repr(e))

    def do_start_plugin(self, arg):
        args = arg.split()
        if len(args) == 1:
            try:
                code, data = self.node.call_method('2:start_plugin', args[0])
                if code == '0':
                    result = json.loads(data)
                    if result['Error']:
                        print(result['Error'])
                    else:
                        print(result['Success'])
                else:
                    print(code, data)
            except Exception as e:
                print(repr(e))
        else:
            print('Error input. example : start_plugin MqttPlugin')

    def do_stop_plugin(self, arg):
        args = arg.split()
        if len(args) == 1:
            try:
                code, data = self.node.call_method('2:stop_plugin', args[0])
                if code == '0':
                    result = json.loads(data)
                    if result['Error']:
                        print(result['Error'])
                    else:
                        print(result['Success'])
                else:
                    print(code, data)
            except Exception as e:
                print(repr(e))
        else:
            print('Error input. example : stop_plugin MqttPlugin')

    def do_getcfg(self, arg):
        args = arg.split()
        if len(args) == 3:
            dirname = os.path.realpath(args[2])
            if os.path.isdir(dirname):
                try:
                    code, data = self.node.call_method('2:getcfg', args[0],
                                                       args[1])
                    if code == '0':
                        result = json.loads(data)
                        if result['Error']:
                            print(result['Error'])
                        else:
                            with open(
                                    os.path.join(
                                        dirname,
                                        result['Success']['filename']),
                                    "w") as f:
                                f.write(result['Success']['data'])
                            print('saved file to %s' % os.path.join(
                                dirname, result['Success']['filename']))
                    else:
                        print(code, data)

                except Exception as e:
                    print(repr(e))

            else:
                print(
                    'folder not exist, please enter the correct directory used to store files'
                )
        else:
            print('Error input. example : getcfg mqttplugin json /home/test/')

    def do_setcfg(self, arg):
        args = arg.split()
        if len(args) == 3:
            if os.path.isfile(os.path.realpath(args[2])):
                fp = os.path.realpath(args[2])
                s = ''
                with open(fp, 'r') as f:
                    s = f.read()

                try:
                    code, data = self.node.call_method('2:setcfg', args[0],
                                                       args[1], s)
                    if code == '0':
                        result = json.loads(data)
                        if result['Error']:
                            print(result['Error'])
                        else:
                            print(result['Success'])
                    else:
                        print(code, data)
                except Exception as e:
                    print(repr(e))

            else:
                print(
                    'source file not exist, please enter the correct path to upload'
                )
        else:
            print(
                'Error input. example : setcfg mqttplugin json /home/test/t.json'
            )

    def do_call(self, arg):
        args = arg.split()
        if len(args) > 1:
            plugin_name = args[0:1][0]
            method_name = args[1:2][0]
            params = args[2:]

            if plugin_name == 'manager':
                print("manager plugin not allow call_method in console tools")
                return

            plugin_node = None
            try:
                plugin_node = self.root.get_child(
                    ["0:Objects", "2:" + plugin_name])
            except BaseException:
                print('Cannot find {0}, please check the plugin is started.'.
                      format(plugin_name))

            if plugin_node:
                methods = plugin_node.get_methods()
                func = None
                for m in methods:
                    if m.get_display_name().Text == method_name:
                        func = m
                if func:
                    try:
                        result = plugin_node.call_method(func, *params)
                        print(result)
                    except BaseException:
                        pass
                else:
                    print('object has not method ({0}).'.format(method_name))
        else:
            print('example : call KvPlugin put key value')

    def do_tree(self, arg):
        args = arg.split()
        if len(args) == 1:
            plugin_name = args[0]
            if plugin_name == 'manager':
                print("manager plugin operation is not supported")
                return

            plugin_node = None
            try:
                plugin_node = self.root.get_child(
                    ["0:Objects", "2:" + plugin_name])
            except BaseException:
                print('Cannot find {0}, please check the plugin is started.'.
                      format(plugin_name))

            if plugin_node:
                listtree(plugin_node, tab=0)
        else:
            print('example : tree KvPlugin')

    def do_exit(self, arg):
        print('GOOD BAY')
        return True

    def preloop(self):
        self.opcua = Client(self.server_uri)
        try:
            self.opcua.connect()
        except BaseException:
            self.bye('Connect opcua server failed. %s' % self.server_uri)
        self.root = self.opcua.get_root_node()
        try:
            self.node = self.root.get_child(["0:Objects", "2:ManagerPlugin"])
        except BaseException:
            self.bye(
                'Cannot find the ManagerPlugin node, maybe the Manager plugin not started.'
            )

    def postloop(self):
        if self.opcua:
            self.opcua.disconnect()

    def default(self, line):
        print('Unknown command, please try help')

    def bye(self, msg):
        print(msg)
        print('Application exit')
        if self.opcua:
            try:
                self.opcua.disconnect()
            except BaseException:
                pass
        exit(1)
Beispiel #41
0
class OpcUaConnector(Thread, Connector):
    def __init__(self, gateway, config, connector_type):
        self._connector_type = connector_type
        self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
        super().__init__()
        self.__gateway = gateway
        self.__server_conf = config.get("server")
        self.__interest_nodes = []
        self.__available_object_resources = {}
        self.__show_map = self.__server_conf.get("showMap", False)
        self.__previous_scan_time = 0
        for mapping in self.__server_conf["mapping"]:
            if mapping.get("deviceNodePattern") is not None:
                self.__interest_nodes.append(
                    {mapping["deviceNodePattern"]: mapping})
            else:
                log.error(
                    "deviceNodePattern in mapping: %s - not found, add property deviceNodePattern to processing this mapping",
                    dumps(mapping))
        if "opc.tcp" not in self.__server_conf.get("url"):
            self.__opcua_url = "opc.tcp://" + self.__server_conf.get("url")
        else:
            self.__opcua_url = self.__server_conf.get("url")
        self.client = Client(
            self.__opcua_url,
            timeout=self.__server_conf.get("timeoutInMillis", 4000) / 1000)
        if self.__server_conf["identity"]["type"] == "cert.PEM":
            try:
                ca_cert = self.__server_conf["identity"].get("caCert")
                private_key = self.__server_conf["identity"].get("privateKey")
                cert = self.__server_conf["identity"].get("cert")
                security_mode = self.__server_conf["identity"].get(
                    "mode", "SignAndEncrypt")
                policy = self.__server_conf["security"]
                if cert is None or private_key is None:
                    log.exception(
                        "Error in ssl configuration - cert or privateKey parameter not found"
                    )
                    raise RuntimeError(
                        "Error in ssl configuration - cert or privateKey parameter not found"
                    )
                security_string = policy + ',' + security_mode + ',' + cert + ',' + private_key
                if ca_cert is not None:
                    security_string = security_string + ',' + ca_cert
                self.client.set_security_string(security_string)

            except Exception as e:
                log.exception(e)
        if self.__server_conf["identity"].get("username"):
            self.client.set_user(
                self.__server_conf["identity"].get("username"))
            if self.__server_conf["identity"].get("password"):
                self.client.set_password(
                    self.__server_conf["identity"].get("password"))

        self.setName(
            self.__server_conf.get(
                "name", 'OPC-UA ' +
                ''.join(choice(ascii_lowercase)
                        for _ in range(5))) + " Connector")
        self.__opcua_nodes = {}
        self._subscribed = {}
        self.__sub = None
        self.data_to_send = []
        self.__sub_handler = SubHandler(self)
        self.__stopped = False
        self.__connected = False
        self.daemon = True

    def is_connected(self):
        return self.__connected

    def open(self):
        self.__stopped = False
        self.start()
        log.info("Starting OPC-UA Connector")

    def run(self):
        while not self.__connected:
            try:
                self.client.connect()
                try:
                    self.client.load_type_definitions()
                except Exception as e:
                    log.debug(e)
                    log.debug("Error on loading type definitions.")
                log.debug(self.client.get_namespace_array()[-1])
                log.debug(
                    self.client.get_namespace_index(
                        self.client.get_namespace_array()[-1]))
            except ConnectionRefusedError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                time.sleep(10)
            except OSError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                time.sleep(10)
            except Exception as e:
                log.debug("error on connection to OPC-UA server.")
                log.error(e)
                time.sleep(10)
            else:
                self.__connected = True
                log.info("OPC-UA connector %s connected to server %s",
                         self.get_name(), self.__server_conf.get("url"))
        self.__initialize_client()
        while not self.__stopped:
            try:
                time.sleep(.1)
                self.__check_connection()
                if not self.__connected and not self.__stopped:
                    self.client.connect()
                    self.__initialize_client()
                    log.info("Reconnected to the OPC-UA server - %s",
                             self.__server_conf.get("url"))
                elif not self.__stopped:
                    if self.__server_conf.get(
                            "disableSubscriptions", False
                    ) and time.time(
                    ) * 1000 - self.__previous_scan_time > self.__server_conf.get(
                            "scanPeriodInMillis", 60000):
                        self.__scan_nodes_from_config()
                        self.__previous_scan_time = time.time() * 1000

                    if self.data_to_send:
                        self.__gateway.send_to_storage(self.get_name(),
                                                       self.data_to_send.pop())
                if self.__stopped:
                    self.close()
                    break
            except (KeyboardInterrupt, SystemExit):
                self.close()
                raise
            except ConnectionRefusedError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                self.client = Client(
                    self.__opcua_url,
                    timeout=self.__server_conf.get("timeoutInMillis", 4000) /
                    1000)
                time.sleep(10)
            except Exception as e:
                self.close()
                log.exception(e)

    def __check_connection(self):
        try:
            node = self.client.get_root_node()
            node.get_children()
            self.__connected = True
        except ConnectionRefusedError:
            self.__connected = False
            self._subscribed = {}
            self.__sub = None
        except OSError:
            self.__connected = False
            self._subscribed = {}
            self.__sub = None
        except FuturesTimeoutError:
            self.__connected = False
            self._subscribed = {}
            self.__sub = None
        except AttributeError:
            self.__connected = False
            self._subscribed = {}
            self.__sub = None
        except Exception as e:
            self.__connected = False
            self._subscribed = {}
            self.__sub = None
            log.exception(e)

    def close(self):
        self.__stopped = True
        if self.__connected:
            self.client.disconnect()
        self.__connected = False
        log.info('%s has been stopped.', self.get_name())

    def get_name(self):
        return self.name

    def on_attributes_update(self, content):
        log.debug(content)
        try:
            for server_variables in self.__available_object_resources[
                    content["device"]]['variables']:
                for attribute in content["data"]:
                    for variable in server_variables:
                        if attribute == variable:
                            server_variables[variable].set_value(
                                content["data"][variable])
        except Exception as e:
            log.exception(e)

    def server_side_rpc_handler(self, content):
        try:
            for method in self.__available_object_resources[
                    content["device"]]['methods']:
                rpc_method = content["data"].get("method")
                if rpc_method is not None and method.get(
                        rpc_method) is not None:
                    arguments_from_config = method["arguments"]
                    arguments = content["data"].get(
                        "params") if content["data"].get(
                            "params") is not None else arguments_from_config
                    try:
                        if isinstance(arguments, list):
                            result = method["node"].call_method(
                                method[rpc_method], *arguments)
                        elif arguments is not None:
                            result = method["node"].call_method(
                                method[rpc_method], arguments)
                        else:
                            result = method["node"].call_method(
                                method[rpc_method])

                        self.__gateway.send_rpc_reply(
                            content["device"], content["data"]["id"], {
                                content["data"]["method"]: result,
                                "code": 200
                            })
                        log.debug("method %s result is: %s",
                                  method[rpc_method], result)
                    except Exception as e:
                        log.exception(e)
                        self.__gateway.send_rpc_reply(content["device"],
                                                      content["data"]["id"], {
                                                          "error": str(e),
                                                          "code": 500
                                                      })
                else:
                    log.error("Method %s not found for device %s", rpc_method,
                              content["device"])
                    self.__gateway.send_rpc_reply(
                        content["device"], content["data"]["id"], {
                            "error": "%s - Method not found" % (rpc_method),
                            "code": 404
                        })
        except Exception as e:
            log.exception(e)

    def __initialize_client(self):
        self.__opcua_nodes["root"] = self.client.get_objects_node()
        self.__opcua_nodes["objects"] = self.client.get_objects_node()
        if not self.__server_conf.get("disableSubscriptions", False):
            self.__sub = self.client.create_subscription(
                self.__server_conf.get("subCheckPeriodInMillis", 500),
                self.__sub_handler)
        else:
            self.__sub = False
        self.__scan_nodes_from_config()
        self.__previous_scan_time = time.time() * 1000
        log.debug('Subscriptions: %s', self.subscribed)
        log.debug("Available methods: %s", self.__available_object_resources)

    def __scan_nodes_from_config(self):
        try:
            if self.__interest_nodes:
                for device_object in self.__interest_nodes:
                    for current_device in device_object:
                        try:
                            device_configuration = device_object[
                                current_device]
                            devices_info_array = self.__search_general_info(
                                device_configuration)
                            for device_info in devices_info_array:
                                if device_info is not None and device_info.get(
                                        "deviceNode") is not None:
                                    self.__search_nodes_and_subscribe(
                                        device_info)
                                    self.__save_methods(device_info)
                                    self.__search_attribute_update_variables(
                                        device_info)
                                else:
                                    log.error(
                                        "Device node is None, please check your configuration."
                                    )
                                    log.debug(
                                        "Current device node is: %s",
                                        str(
                                            device_configuration.get(
                                                "deviceNodePattern")))
                                    break
                        except BrokenPipeError:
                            log.debug("Broken Pipe. Connection lost.")
                        except OSError:
                            log.debug("Stop on scanning.")
                        except Exception as e:
                            log.exception(e)
                log.debug(self.__interest_nodes)
        except Exception as e:
            log.exception(e)

    def __search_nodes_and_subscribe(self, device_info):
        information_types = {
            "attributes": "attributes",
            "timeseries": "telemetry"
        }
        for information_type in information_types:
            for information in device_info["configuration"][information_type]:
                information_key = information["key"]
                config_path = TBUtility.get_value(information["path"],
                                                  get_tag=True)
                information_path = self._check_path(config_path,
                                                    device_info["deviceNode"])
                information["path"] = '${%s}' % information_path
                information_nodes = []
                self.__search_node(device_info["deviceNode"],
                                   information_path,
                                   result=information_nodes)
                for information_node in information_nodes:
                    if information_node is not None:
                        information_value = information_node.get_value()
                        log.debug(
                            "Node for %s \"%s\" with path: %s - FOUND! Current values is: %s",
                            information_type, information_key,
                            information_path, str(information_value))
                        if device_info.get("uplink_converter") is None:
                            configuration = {
                                **device_info["configuration"], "deviceName":
                                device_info["deviceName"],
                                "deviceType":
                                device_info["deviceType"]
                            }
                            if device_info["configuration"].get(
                                    'converter') is None:
                                converter = OpcUaUplinkConverter(configuration)
                            else:
                                converter = TBUtility.check_and_import(
                                    self._connector_type, configuration)
                            device_info["uplink_converter"] = converter
                        else:
                            converter = device_info["uplink_converter"]
                        self.subscribed[information_node] = {
                            "converter": converter,
                            "path": information_path,
                            "config_path": config_path
                        }
                        if not device_info.get(
                                information_types[information_type]):
                            device_info[
                                information_types[information_type]] = []
                        converted_data = converter.convert(
                            (config_path, information_path), information_value)
                        self.statistics['MessagesReceived'] += 1
                        self.data_to_send.append(converted_data)
                        self.statistics['MessagesSent'] += 1
                        if self.__sub is None:
                            self.__sub = self.client.create_subscription(
                                self.__server_conf.get(
                                    "subCheckPeriodInMillis", 500),
                                self.__sub_handler)
                        if self.__sub:
                            self.__sub.subscribe_data_change(information_node)
                        log.debug("Added subscription to node: %s",
                                  str(information_node))
                        log.debug("Data to ThingsBoard: %s", converted_data)
                    else:
                        log.error(
                            "Node for %s \"%s\" with path %s - NOT FOUND!",
                            information_type, information_key,
                            information_path)

    def __save_methods(self, device_info):
        try:
            if self.__available_object_resources.get(
                    device_info["deviceName"]) is None:
                self.__available_object_resources[
                    device_info["deviceName"]] = {}
            if self.__available_object_resources[
                    device_info["deviceName"]].get("methods") is None:
                self.__available_object_resources[
                    device_info["deviceName"]]["methods"] = []
            if device_info["configuration"].get("rpc_methods", []):
                node = device_info["deviceNode"]
                for method_object in device_info["configuration"][
                        "rpc_methods"]:
                    method_node_path = self._check_path(
                        method_object["method"], node)
                    methods = []
                    self.__search_node(node,
                                       method_node_path,
                                       True,
                                       result=methods)
                    for method in methods:
                        if method is not None:
                            node_method_name = method.get_display_name().Text
                            self.__available_object_resources[
                                device_info["deviceName"]]["methods"].append({
                                    node_method_name:
                                    method,
                                    "node":
                                    node,
                                    "arguments":
                                    method_object.get("arguments")
                                })
                        else:
                            log.error(
                                "Node for method with path %s - NOT FOUND!",
                                method_node_path)
        except Exception as e:
            log.exception(e)

    def __search_attribute_update_variables(self, device_info):
        try:
            if device_info["configuration"].get("attributes_updates", []):
                node = device_info["deviceNode"]
                device_name = device_info["deviceName"]
                if self.__available_object_resources.get(device_name) is None:
                    self.__available_object_resources[device_name] = {}
                if self.__available_object_resources[device_name].get(
                        "variables") is None:
                    self.__available_object_resources[device_name][
                        "variables"] = []
                for attribute_update in device_info["configuration"][
                        "attributes_updates"]:
                    attribute_path = self._check_path(
                        attribute_update["attributeOnDevice"], node)
                    attribute_nodes = []
                    self.__search_node(node,
                                       attribute_path,
                                       result=attribute_nodes)
                    for attribute_node in attribute_nodes:
                        if attribute_node is not None:
                            self.__available_object_resources[device_name][
                                "variables"].append({
                                    attribute_update["attributeOnThingsBoard"]:
                                    attribute_node
                                })
                        else:
                            log.error(
                                "Attribute update node with path \"%s\" - NOT FOUND!",
                                attribute_path)
        except Exception as e:
            log.exception(e)

    def __search_general_info(self, device):
        result = []
        match_devices = []
        self.__search_node(self.__opcua_nodes["root"],
                           TBUtility.get_value(device["deviceNodePattern"],
                                               get_tag=True),
                           result=match_devices)
        for device_node in match_devices:
            if device_node is not None:
                result_device_dict = {
                    "deviceName": None,
                    "deviceType": None,
                    "deviceNode": device_node,
                    "configuration": deepcopy(device)
                }
                name_pattern_config = device["deviceNamePattern"]
                name_expression = TBUtility.get_value(name_pattern_config,
                                                      get_tag=True)
                if "${" in name_pattern_config and "}" in name_pattern_config:
                    log.debug("Looking for device name")
                    name_path = self._check_path(name_expression, device_node)
                    device_name_node = []
                    self.__search_node(device_node,
                                       name_path,
                                       result=device_name_node)
                    device_name_node = device_name_node[0]
                    if device_name_node is not None:
                        device_name_from_node = device_name_node.get_value()
                        full_device_name = name_pattern_config.replace(
                            "${" + name_expression + "}",
                            str(device_name_from_node)).replace(
                                name_expression, str(device_name_from_node))
                    else:
                        log.error(
                            "Device name node not found with expression: %s",
                            name_expression)
                        return None
                else:
                    full_device_name = name_expression
                result_device_dict["deviceName"] = full_device_name
                log.debug("Device name: %s", full_device_name)
                if device.get("deviceTypePattern"):
                    device_type_expression = TBUtility.get_value(
                        device["deviceTypePattern"], get_tag=True)
                    if "${" in device_type_expression and "}" in device_type_expression:
                        type_path = self._check_path(device_type_expression,
                                                     device_node)
                        device_type_node = []
                        self.__search_node(device_node,
                                           type_path,
                                           result=device_type_node)
                        device_type_node = device_type_node[0]
                        if device_type_node is not None:
                            device_type = device_type_node.get_value()
                            full_device_type = device_type_expression.replace(
                                "${" + device_type_expression + "}",
                                device_type).replace(device_type_expression,
                                                     device_type)
                        else:
                            log.error(
                                "Device type node not found with expression: %s",
                                device_type_expression)
                            full_device_type = "default"
                    else:
                        full_device_type = device_type_expression
                    result_device_dict["deviceType"] = full_device_type
                    log.debug("Device type: %s", full_device_type)
                else:
                    result_device_dict["deviceType"] = "default"
                result.append(result_device_dict)
            else:
                log.error(
                    "Device node not found with expression: %s",
                    TBUtility.get_value(device["deviceNodePattern"],
                                        get_tag=True))
        return result

    def __search_node(self,
                      current_node,
                      fullpath,
                      search_method=False,
                      result=None):
        if result is None:
            result = []
        try:
            if regex.match(r"ns=\d*;[isgb]=.*", fullpath, regex.IGNORECASE):
                if self.__show_map:
                    log.debug("Looking for node with config")
                node = self.client.get_node(fullpath)
                if node is None:
                    log.warning("NODE NOT FOUND - using configuration %s",
                                fullpath)
                else:
                    log.debug("Found in %s", node)
                    result.append(node)
            else:
                fullpath_pattern = regex.compile(fullpath)
                for child_node in current_node.get_children():
                    new_node = self.client.get_node(child_node)
                    new_node_path = '\\\\.'.join(
                        char.split(":")[1]
                        for char in new_node.get_path(200000, True))
                    if self.__show_map:
                        log.debug("SHOW MAP: Current node path: %s",
                                  new_node_path)
                    new_node_class = new_node.get_node_class()
                    regex_fullmatch = regex.fullmatch(fullpath_pattern, new_node_path.replace('\\\\.', '.')) or \
                                      new_node_path.replace('\\\\', '\\') == fullpath.replace('\\\\', '\\') or \
                                      new_node_path.replace('\\\\', '\\') == fullpath
                    regex_search = fullpath_pattern.fullmatch(new_node_path.replace('\\\\.', '.'), partial=True) or \
                                      new_node_path.replace('\\\\', '\\') in fullpath.replace('\\\\', '\\')
                    if regex_fullmatch:
                        if self.__show_map:
                            log.debug(
                                "SHOW MAP: Current node path: %s - NODE FOUND",
                                new_node_path.replace('\\\\', '\\'))
                        result.append(new_node)
                    elif regex_search:
                        if self.__show_map:
                            log.debug(
                                "SHOW MAP: Current node path: %s - NODE FOUND",
                                new_node_path)
                        if new_node_class == ua.NodeClass.Object:
                            if self.__show_map:
                                log.debug("SHOW MAP: Search in %s",
                                          new_node_path)
                            self.__search_node(new_node,
                                               fullpath,
                                               result=result)
                        elif new_node_class == ua.NodeClass.Variable:
                            log.debug("Found in %s", new_node_path)
                            result.append(new_node)
                        elif new_node_class == ua.NodeClass.Method and search_method:
                            log.debug("Found in %s", new_node_path)
                            result.append(new_node)
        except CancelledError:
            log.error(
                "Request during search has been canceled by the OPC-UA server."
            )
        except BrokenPipeError:
            log.error("Broken Pipe. Connection lost.")
        except OSError:
            log.debug("Stop on scanning.")
        except Exception as e:
            log.exception(e)

    def _check_path(self, config_path, node):
        if regex.match(r"ns=\d*;[isgb]=.*", config_path, regex.IGNORECASE):
            return config_path
        if re.search(r"^root", config_path.lower()) is None:
            node_path = '\\\\.'.join(
                char.split(":")[1] for char in node.get_path(200000, True))
            if config_path[-3:] != '\\.':
                information_path = node_path + '\\\\.' + config_path.replace(
                    '\\', '\\\\')
            else:
                information_path = node_path + config_path.replace(
                    '\\', '\\\\')
        else:
            information_path = config_path
        result = information_path[:]
        return result

    @property
    def subscribed(self):
        return self._subscribed
Beispiel #42
0
class TankSystem:
    def __init__(self):
        self.client = None
        self.objects_node = None
        self.root_node = None
        self.connected = False
        self.sub_handler = SubHandler()

        self.max_size = 600
        self.past_values = {
            'time': collections.deque(maxlen=self.max_size),
            'tank_1': collections.deque(maxlen=self.max_size),
            'tank_2': collections.deque(maxlen=self.max_size),
            'tank_3': collections.deque(maxlen=self.max_size),
            'tank_4': collections.deque(maxlen=self.max_size),
            'valve_1': collections.deque(maxlen=self.max_size),
            'valve_2': collections.deque(maxlen=self.max_size),
        }

        self.seconds = time.time()
        self.start_time = time.time()
        self.logging_time = 1

    def connect(self):
        if not self.connected:
            # self.client = Client('opc.tcp://192.168.1.23:4840/freeopcua/server/')
            self.client = Client(
                'opc.tcp://192.168.1.23:4840/freeopcua/server/')
            self.client.connect()
            self.objects_node = self.client.get_objects_node()
            self.connected = True
            self.log_values()

            self.root_node = self.client.get_root_node()
            myevent = self.root_node.get_child([
                '0:Types', '0:EventTypes', '0:BaseEventType', '2:Alarma_nivel'
            ])

            obj = self.objects_node.get_child(
                ['2:Proceso_Tanques', '2:Alarmas', '2:Alarma_nivel'])

            sub = self.client.create_subscription(100, self.sub_handler)
            handle = sub.subscribe_events(obj, myevent)

            # sub.unsubscribe(handle)
            # sub.delete()

    def disconnect(self):
        if self.connected:
            self.connected = False
            self.client.disconnect()
            self.client = None
            self.objects_node = None
            self.past_values = {
                'time': collections.deque(maxlen=self.max_size),
                'tank_1': collections.deque(maxlen=self.max_size),
                'tank_2': collections.deque(maxlen=self.max_size),
                'tank_3': collections.deque(maxlen=self.max_size),
                'tank_4': collections.deque(maxlen=self.max_size),
                'valve_1': collections.deque(maxlen=self.max_size),
                'valve_2': collections.deque(maxlen=self.max_size),
            }

    @property
    def tank_1(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Tanques', '2:Tanque1', '2:h'])
        value = node.get_value()
        return value

    @property
    def tank_2(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Tanques', '2:Tanque2', '2:h'])
        value = node.get_value()
        return value

    @property
    def tank_3(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Tanques', '2:Tanque3', '2:h'])
        value = node.get_value()
        return value

    @property
    def tank_4(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Tanques', '2:Tanque4', '2:h'])
        value = node.get_value()
        return value

    @property
    def valve_1(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Valvulas', '2:Valvula1', '2:u'])
        value = node.get_value()
        return value

    @valve_1.setter
    def valve_1(self, value):

        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Valvulas', '2:Valvula1', '2:u'])
        node.set_value(value)

    @property
    def valve_2(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Valvulas', '2:Valvula2', '2:u'])
        value = node.get_value()
        return value

    @valve_2.setter
    def valve_2(self, value):

        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Valvulas', '2:Valvula2', '2:u'])
        node.set_value(value)

    @property
    def gamma_1(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Razones', '2:Razon1', '2:gamma'])
        value = node.get_value()
        return value

    @gamma_1.setter
    def gamma_1(self, value):

        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Razones', '2:Razon1', '2:gamma'])
        node.set_value(value)

    @property
    def gamma_2(self):
        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Razones', '2:Razon2', '2:gamma'])
        value = node.get_value()
        return value

    @gamma_2.setter
    def gamma_2(self, value):

        node = self.objects_node.get_child(
            ['2:Proceso_Tanques', '2:Razones', '2:Razon2', '2:gamma'])
        node.set_value(value)

    def log_values(self):
        if self.connected:
            self.seconds = time.time()
            self.past_values['time'].append(
                round(time.time() - self.start_time, 3))
            self.past_values['tank_1'].append(round(self.tank_1, 3))
            self.past_values['tank_2'].append(round(self.tank_2, 3))
            self.past_values['tank_3'].append(round(self.tank_3, 3))
            self.past_values['tank_4'].append(round(self.tank_4, 3))
            self.past_values['valve_1'].append(round(self.valve_1, 3))
            self.past_values['valve_2'].append(round(self.valve_2, 3))
Beispiel #43
0
class Subscriber():
    """Create a service to monitor OPC nodes.
    """
    def __init__(self, callback, **params):
        """Instantiate an the base class OPC client.

        Arguments
        callback (func): Function to call on node value changes.
        params (dict): Configuration parameters to start service.
            The dictionary should contain:
            endpoint (str): OPC server address
            uri (str): the namespace for the nodes
            obj (str): the parent object node of the nodes
            nodes (dict): Keys are the name of the nodes to monitor. The
                values are dictionaries:
                    "respond": node to respond
            watchdog (optional) (str): the name of the node used for
                the watchdog
        """
        self._callback = callback
        self._params = params

    def _connect(self, endpoint):
        """Conncect to the OPC UA server.

        Arguments
        endpoint (str): OPC server address
        """
        self._client = Client(endpoint)
        self._client.connect()

    def _get_nodes(self, idx, obj, names):
        """Get links to the OPC nodes.

        Arguments
        idx (int): Namespace index
        obj (str): Object name
        names (list): List of string of node names

        returns (list): List of Nodes
        """
        idx = self._client.get_namespace_index(idx)
        root = self._client.get_root_node()
        nodes = [root.get_child(self._get_path(idx, obj, n)) for n in names]
        return nodes

    def _get_path(self, idx, obj, name):
        """Make a browse path list from the namespace index and object and
        node name.

        Arguments
        idx (int): Namespace index
        obj (str): Object name
        name (str): Name of node

        Return (list) browse path
        """
        bp = ["0:Objects", f"{idx}:{obj}", f"{idx}:{name}"]
        return bp

    def _get_name(self, node):
        """
        Get the name of the node from the mapping.

        Arguments
        node (node): Node object

        return (str) name associated with node
        """
        return [k for k, v in self._map.items() if v == node][0]

    def _create_node_map(self):
        """Create a map between node names and Node objects
        for fast lookup.
        """
        # Get all the nodes defined in the parameters dictionary.
        names = list(self._params["nodes"].keys())\
            + [v["respond"] for k, v in self._params["nodes"].items()]
        if "watchdog" in self._params:
            names += [
                self._params["watchdog"]["controller"],
                self._params["watchdog"]["instrument"]
            ]

        nodes = self._get_nodes(self._params["uri"], self._params["obj"],
                                names)

        return {k: v for k, v in zip(names, nodes)}

    def _get_monitor_nodes(self):
        """Get the nodes to be monitored.
        """
        names = list(self._params["nodes"].keys())
        if "watchdog" in self._params:
            names += [self._params["watchdog"]["controller"]]

        return self._get_nodes(self._params["uri"], self._params["obj"], names)

    def _update_watchdog(self, val):
        """Update the watchdog. This is handled at the subscription
        service level and not instrument to reduce CPU overhead.

        Arguments
        val (?): The value to return to the watchdog tag.
        """
        # self.respond(self._params["watchdog"]["instrument"], val)

    def respond(self, node, value):
        """Write a value to the node.

        Arguments
        node (str): String associated with node (see self._map)
        value (varries): value to write
        """
        self._map[node].set_value(value)

    def datachange_notification(self, node, val, data):
        """This method is called on subscribed node changes.
        see https://python-opcua.readthedocs.io/en/latest/subscription.html
        """
        # If the node is the watchdog node, then update without
        # calling instrument method to reduce CPU cycles.
        if "watchdog" in self._params:
            if node == self._map[self._params["watchdog"]["controller"]]:
                self._update_watchdog(val)
        else:
            name = self._get_name(node)
            # Call the instrument callback with the node information:
            #     desired run command,
            #     callback to the respond method with the node as parameter
            self._callback(
                command=self._params["nodes"][name]["command"],
                parameters=val,
                callback=lambda x: self.respond(
                    self._params["nodes"][name]["respond"], x),
            )

    def run(self):
        """Connect to client, and subscribe to nodes.
        """
        self._connect(self._params["endpoint"])
        self._map = self._create_node_map()
        sub = self._client.create_subscription(1000, self)
        nodes = self._get_monitor_nodes()
        handle = sub.subscribe_data_change(nodes)
        logger.info("OPC subscription started")

    def event_notification(self, event):
        print("Python: New event", event)


if __name__ == "__main__":
    logging.basicConfig(level=logging.WARN)
    #logger = logging.getLogger("KeepAlive")
    #logger.setLevel(logging.DEBUG)

    #Set according to the OPC UA network
    #client = Client("opc.tcp://127.0.0.1:12686/AI4.0-Ontology-Example")
    client = Client("opc.tcp://192.168.1.7:12686/AI4.0-Ontology-Example")
    try:
        client.connect()
        client.load_type_definitions()  # load definition of server specific structures/extension objects

        # Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
        root = client.get_root_node()
        print("Root node is: ", root)
        objects = client.get_objects_node()
        print("Objects node is: ", objects)

        # Node objects have methods to read and write node attributes as well as browse or populate address space
        print("Children of root are: ", root.get_children())

        ###States
        state0Node = client.get_node("ns=2;s=A-I4.0-Ontology/Metal-Separation-Process/States/State 0")
        state0_value = state0Node.get_value()
        state1Node = client.get_node("ns=2;s=A-I4.0-Ontology/Metal-Separation-Process/States/State 1")
Beispiel #45
0
class microKWKKcom(object):

    variables_location = ["0:Objects", "4:PLC1", "4:GVL_OPC_Variablen"]

    devices = {
        "CHP_H_W_Q_M___": "4:QthChp",
        "CHP_H_W_PT_M___": "4:PthChp",
        "CHP_H_W_VF_M___": "4:VdotChp",
        "CHP_H_W_T_M__FL_": "4:TflChp",
        "CHP_H_W_T_M__RL_": "4:TrlChp",
        "CHP_H_W_dT_M___": "4:VHmChp",
        "CHP_H_E_PE_M___": "4:PelChp",
        "CHP_H_F_VF_M___": "4:VdotFuel",
        "CHP_H_F_IMP_M___": "4:VdotFuelImp",
        "CHP_H_W_B_O___": "4:OnChp",
        "CHP_H_E_B_O___": "4:OnVoltageChp",
        "CHP_H_E_Q_M__FL_": "4:QelChpIn",
        "CHP_H_E_Q_M__RL_": "4:QelChpOut",
        "ADCM_C_W_Q_M_LT__": "4:QthAdcmLt",
        "ADCM_C_W_PT_M_LT__": "4:PthAdcmLt",
        "ADCM_C_W_VF_M_LT__": "4:VdotAdcmLt",
        "ADCM_C_W_T_M_LT_FL_": "4:TflAdcmLt",
        "ADCM_C_W_T_M_LT_RL_": "4:TrlAdcmLt",
        "ADCM_C_W_dT_M_LT__": "4:VHmAdcmLt",
        "ADCM_C_W_Q_M_MT__": "4:QthAdcmMt",
        "ADCM_C_W_PT_M_MT__": "4:PthAdcmMt",
        "ADCM_C_W_VF_M_MT__": "4:VdotAdcmMt",
        "ADCM_C_W_T_M_MT_FL_": "4:TflAdcmMt",
        "ADCM_C_W_T_M_MT_RL_": "4:TrlAdcmMt",
        "ADCM_C_W_dT_M_MT__": "4:VHmAdcmMt",
        "ADCM_C_W_Q_M_HT__": "4:QthAdcmHt",
        "ADCM_C_W_PT_M_HT__": "4:PthAdcmHt",
        "ADCM_C_W_VF_M_HT__": "4:VdotAdcmHt",
        "ADCM_C_W_T_M_HT_FL_": "4:TflAdcmHt",
        "ADCM_C_W_T_M_HT_RL_": "4:TrlAdcmHt",
        "ADCM_C_W_dT_M_HT__": "4:VHmAdcmHt",
        "ADCM_C_E_PE_M___": "4:PelAdcm",
        "ADCM_C_W_B_O___": "4:OnAdcm",
        "ADCM_C_W_TSET_O_LT__": "4:TsetAdcm",
        "ADCM_C_W_VSET_M_MT__": "4:VAdcmCt",
        "RevHP_HC_W_Q_M_LT__": "4:QthCcmLt",
        "RevHP_HC_W_PT_M_LT__": "4:PthCcmLt",
        "RevHP_HC_W_VF_M_LT__": "4:VdotCcmLt",
        "RevHP_HC_W_T_M_LT_FL_": "4:TflCcmLt",
        "RevHP_HC_W_T_M_LT_RL_": "4:TrlCcmLt",
        "RevHP_HC_W_dT_M_LT__": "4:VHmCcmLt",
        "RevHP_HC_W_Q_M_MT__": "4:QthCcmCkd",
        "RevHP_HC_W_PT_M_MT__": "4:PthCcmCkd",
        "RevHP_HC_W_VF_M_MT__": "4:VdotCcmCkd",
        "RevHP_HC_W_T_M_MT_FL_": "4:TflCcmCkd",
        "RevHP_HC_W_T_M_MT_RL_": "4:TrlCcmCkd",
        "RevHP_HC_W_dT_M_MT__": "4:VHmCcmCkd",
        "RevHP_HC_E_PE_M___": "4:PelCcm",
        "RevHP_HC_W_B_O___": "4:OnCcm",
        "RevHP_C_W_B_O___": "4:CoolingCcm",
        "OC_HC_B_Q_M___": "4:QthCt",
        "OC_HC_B_PT_M___": "4:PthCt",
        "OC_HC_B_VF_M___": "4:VdotCt",
        "OC_HC_B_T_M__FL_": "4:TrlCt",
        "OC_HC_B_T_M__RL_": "4:TflCt",
        "OC_HC_B_dT_M___": "4:VHmCt",
        "OC_HC_E_PE_M___": "4:PelCt",
        "OC_HC_B_B_O___": "4:OnCt",
        "OC_HC_B_PSET_O___": "4:VsetCt",
        "OC_HC_E_B_O___": "4:ModeCt",
        "LOAD_HC_W_Q_M___": "4:QthLoad",
        "LOAD_HC_W_PT_M___": "4:PthLoad",
        "LOAD_HC_W_VF_M___": "4:VdotLoad",
        "LOAD_HC_W_T_M__FL_": "4:TflLoad",
        "LOAD_HC_W_T_M__RL_": "4:TrlLoad",
        "LOAD_HC_W_dT_M___": "4:VHmLoad",
        "PU_HC_B_B_O_MT__": "4:OnP5AdcmMt",
        "PU_HC_W_B_O_LT_RevHp_": "4:OnP6CcmLt",
        "PU_HC_W_B_O_MT_RevHp_": "4:OnP7CcmMt",
        "PU_H_W_B_O__MX_": "4:OnP8HtesCtes",
        "PU_H_W_B_O_MT_HTES_": "4:OnP11Htes",
        "PU_H_W_B_O_IT_HTES_": "4:OnP12Htes",
        "PU_H_W_B_O_HT_RevHP_": "4:OnP13RevHpW2",
        "HTES_H_W_T_M_IT_1_": "4:HT01",
        "HTES_H_W_T_M_IT_2_": "4:HT02",
        "HTES_H_W_T_M_IT_3_": "4:HT03",
        "HTES_H_W_T_M_IT_4_": "4:HT04",
        "HTES_H_W_T_M_IT_5_": "4:HT05",
        "HTES_H_W_T_M_IT_6_": "4:HT06",
        "HTES_H_W_T_M_IT_7_": "4:HT07",
        "HTES_H_W_T_M_IT_8_": "4:HT08",
        "HTES_H_W_T_M_IT_9_": "4:HT09",
        "CTES_C_W_T_M_IT_1_": "4:CT01",
        "CTES_C_W_T_M_IT_2_": "4:CT02",
        "CTES_C_W_T_M_IT_3_": "4:CT03",
        "CTES_C_W_T_M_IT_4_": "4:CT04",
        "COIL_H_W_B_O_IT__": "4:OnCoil",
        "COIL_H_E_PE_M___": "4:PelCoil",
        "ASL_H_W_B_O_IT_FL_": "4:LeftAsl",
        "ASL_H_W_B_O_IT_RL_": "4:RightAsl",
        "ASL_H_W_T_M_IT_FL_": "4:AslTcl",
        "SV_HC_W_B_O__FL_": "4:OpenSo1",
        "SV_HC_W_B_O__RL_": "4:OpenSo2",
        "MV_HC_W_B_O_FL_1_": "4:OpenMv1",
        "MV_HC_W_B_O_FL_2_": "4:OpenMv2",
        "MV_HC_W_B_O_RL_1_": "4:CloseMv1",
        "MV_HC_W_B_O_RL_2_": "4:CloseMv2",
        "AUX_HC_E_PE_M___": "4:PelAux",
        "AUX_HC_A_T_M___": "4:Tamb",
        "KWKK_SPStime": "4:SPSzeit",
        "KWKK_SPSrun": "4:SPSrun",
        "KWKK_CtrlMode": "4:OpModeAuto",
        "NotAusAktiv": "4:NotAusAktiv",
        "Optimal_Mode": "4:Optimal_Mode"
    }

    def __init__(self, server_address=None, server_port=None):

        self.server_address = server_address
        self.server_port = server_port

        self.client = Client("opc.tcp://" +str(self.server_address) + ":" + \
                             str(self.server_port))
        self.client.connect()

        self.root = self.client.get_root_node()

    def __del__(self):

        self.client.disconnect()

    def set_value(self, device="", value=""):
        """
        Assign a value to the specified device listed on the dictionary (use labview name)
        These values have to match the data type set on the PLC (SPS). eg. float, UInt16, etc.
        The SPS can recieve either a variant or a datavalue variable, but it seems to accept 
        more the Datavalue as in Set_Value, therefore its better to send it this way.
        Refer to uatypes.py for more information regarding variant types. 
        the Timestamp also on uatypes.py has to be set to 0 or none.
        https://github.com/FreeOpcUa/python-opcua/issues/9
              
        """

        child = self.root.get_child(self.variables_location + \
                                    [self.devices[str(device)]])

        if isinstance(value, float):

            dv = ua.DataValue(ua.Variant(float(value), ua.VariantType.Float))
        elif isinstance(value, bool):
            dv = ua.DataValue(ua.Variant(bool(value), ua.VariantType.Boolean))
        else:
            print(
                'At the moment Bool and Float variant types are accepted, for adding'
                'an extra type please refer to microkwkkcom.py document')

        child.set_value(dv)

        value = child.get_value()

        return {device: value}

    def get_value(self, device=""):
        """
        Retrieve the value from the listed device contained on the dictionary
              
        """

        child = self.root.get_child(self.variables_location + \
                                    [self.devices[str(device)]])
        value = child.get_value()

        return {device: value}

    def get_all_values(self):
        """
        Retrieve the value from the listed device contained on the dictionary
              
        """

        values = {}

        for device in self.devices:

            values.update(self.get_value(device=device))

        return values
Beispiel #46
0
class OPCUAServer(object):
    """
    Each instance of this class manages a connection to its own OPC UA server.
    Methods are called to get node data from the server.
    """
    def __init__(self,
                 name,
                 endPointAddress,
                 nameSpaceUri=None,
                 browseRootNodeIdentifier=None):
        # ---------- Setup -----------
        self.name = name
        self.logger = logging.getLogger(self.name)
        self.endPointAddress = endPointAddress
        self.nameSpaceUri = nameSpaceUri
        self.nameSpaceIndex = None
        self.browseRootNodeIdentifier = browseRootNodeIdentifier
        self.rootNodeId = None
        self.client = Client(self.endPointAddress, timeout=2)
        self.sub = None
        self.subscriptions = {}
        # ----------------------------

    def check_connection(self):
        """
        Check if a connection has been established before
        or if connection thread is running.

        If either fails, try to (re)connect.
        """

        if self.client.uaclient._uasocket is None:
            self.connect()
        elif self.client.uaclient._uasocket._thread is None:
            self.connect()
        elif not self.client.uaclient._uasocket._thread.is_alive():
            self.connect()

    def connect(self):
        """
        Connect to OPC UA server.
        If fails clean up session and socket, and raise exception.
        """

        try:
            self.logger.info("Connecting to " + self.name + ".")
            self.client.connect()
            self.update_namespace_and_root_node_id()
        except socket.timeout:
            self.logger.info(self.name + " socket timed out.")
            try:
                self.logger.info("Cleaning up session and socket.")
                self.client.uaclient.disconnect()
            except AttributeError:
                pass
            self.logger.info("Socket and session cleaned up.")
            raise TimeoutError(self.name + " timed out.")

    def update_namespace_and_root_node_id(self):
        """
        Update rootNodeId and nameSpaceIndex.
        If no namespace given, sets root node (id: i=84) as root node.
        """

        if self.nameSpaceUri and self.browseRootNodeIdentifier:
            nsArray = self.client.get_namespace_array()
            index = nsArray.index(self.nameSpaceUri)
            if index > 0:
                nodeId = "ns={};".format(index) + self.browseRootNodeIdentifier
            else:
                nodeId = self.browseRootNodeIdentifier
        else:
            nodeId = "i=84"
            index = None

        self.rootNodeId = nodeId
        self.nameSpaceIndex = index
        return

    def get_node_path(self, nodeId):
        """
        Create node path from node id for current server settings.
        Attempts to create a path of node from rootNode.
        Only works for folderly like string node ids.
        Example: "ns=2;s=node1.node2.node3.node4"
        """

        identifierType = self.rootNodeId.split(";")[-1].split("=")[0]
        if (identifierType == "s") and ("." in self.rootNodeId):
            rootNodeName = self.rootNodeId.lower().split(".")[-1]
            nodePath = nodeId.lower().split(rootNodeName)[-1]
            nodePath = nodePath.replace(".", "", 1).replace(".", "/")
        else:
            nodePath = nodeId.split("=")[-1]

        return nodePath

    def get_node(self, nodeId=""):
        """
        Returns node from nodeId or identifier.
        If no namespace given in nodeId,
        assumes the namespace to namespace given for the server in settings.py.
        Only the ns set for the server in servers.json is accessible via
        browsing.
        """

        self.check_connection()

        if nodeId == "":
            nodeId = self.rootNodeId
        elif self.nameSpaceIndex is None:
            nodeId = nodeId
        elif nodeId[:3] == "ns=":
            identifier = nodeId.split(";")[-1]
            if self.nameSpaceIndex == 0:
                nodeId = identifier
            else:
                nodeId = f"ns={self.nameSpaceIndex};{identifier}"
        else:
            nodeId = f"ns={self.nameSpaceIndex};{nodeId}"

        return self.client.get_node(nodeId)

    async def get_variable_nodes(self,
                                 node,
                                 nodeClass=2,
                                 variableList=None,
                                 depth=0,
                                 maxDepth=10):
        """
        Eats a list of node object(s).
        Recursively finds nodes under given nodes that have given nodeClass.
        Returns node objects in a list.
        """

        if variableList is None:
            variableList = []

        depth += 1
        if depth >= maxDepth:
            return variableList

        nodes = node.get_children()
        params = ua.ReadParameters()
        for node in nodes:
            rv = ua.ReadValueId()
            rv.NodeId = node.nodeid
            rv.AttributeId = ua.AttributeIds.NodeClass
            params.NodesToRead.append(rv)

        results = []
        if len(params.NodesToRead) > 0:
            results, readTime = await self.read(params)

        for i in range(len(results)):
            if nodeClass == results[i].Value.Value:
                variableList.append(nodes[i])
            await self.get_variable_nodes(node=nodes[i],
                                          nodeClass=nodeClass,
                                          variableList=variableList,
                                          depth=depth)

        return variableList

    def subscribe_variable(self, nodeId):

        if self.sub is None:
            handler = self
            self.sub = self.client.create_subscription(100, handler)

        node = self.get_node(nodeId)
        if 2 == node.get_attribute(ua.AttributeIds.NodeClass).Value.Value:
            return self.sub.subscribe_data_change(node)
        else:
            return None

    def datachange_notification(self, node, value, data):

        self.subscriptions[node.nodeid.to_string()] = data.monitored_item.Value

    async def read_node_attribute(self, nodeId, attribute):
        """
        Read node attribute based on given arguments.
        Giving correct dataType for value and node speeds
        up the write operation.

        Arguments                               Example
        nodeId:     Target nodeId               "ns=2;i=2"
        attribute:  Target attribute of node    "Value"

        Results
        OPCUAVar:   OPC UA variable object      <object>
        readTime:   Time taken for read (ns)    12345678
        """

        rv = ua.ReadValueId()
        if nodeId == "":
            rv.NodeId = ua.NodeId.from_string(server.rootNodeId)
        else:
            rv.NodeId = ua.NodeId.from_string(nodeId)
        rv.AttributeId = ua.AttributeIds[attribute]

        params = ua.ReadParameters()
        params.NodesToRead.append(rv)

        result, readTime = await self.read(params)
        if attribute == "Value":
            return result[0], readTime
        else:
            return result[0]

    async def set_node_attribute(self,
                                 nodeId,
                                 attribute,
                                 value,
                                 dataType=None):
        """
        Sets node attribute based on given arguments.
        Giving correct dataType for value and node speeds
        up the write operation.

        Arguments                               Example
        nodeId:     Target nodeId               "ns=2;i=2"
        attribute:  Target attribute of node    "Value"
        value:      Value for the attribute     1234
        dataType:   Data type of value          "Int32"

        Results
        boolean:    Indicates success           True
        writeTime:  Time taken for write (ns)   12345678
        """

        attr = ua.WriteValue()

        if nodeId == "":
            attr.NodeId = ua.NodeId.from_string(self.rootNodeId)
        else:
            attr.NodeId = ua.NodeId.from_string(nodeId)

        attr.AttributeId = ua.AttributeIds[attribute]

        if attribute == "Description":
            dataValue = ua.LocalizedText(value)
        else:
            if dataType is None:
                variantType = self.variant_type_finder(value, nodeId)
            else:
                variantType = ua.VariantType[dataType]
            dataValue = ua.Variant(value, variantType)
        attr.Value = ua.DataValue(dataValue)

        params = ua.WriteParameters()
        params.NodesToWrite.append(attr)

        result, writeTime = await self.write(params)
        if attribute == "Value":
            return result[0].is_good(), writeTime
        else:
            return result[0].is_good()

    def add_node(self, name, nodeId, parentId, value=None, writable=True):
        """
        Adds a node to OPC UA server.
        If value given, adds a variable node, else, a folder node.
        Requires server admin powers in server servers.json, for example
        endPointAddress: "opc.tcp://[email protected]:4840/freeopcua/server/".
        """

        self.check_connection()

        if self.nameSpaceIndex is not None:
            index = self.nameSpaceIndex
        elif nodeId[:3] == "ns=":
            index = nodeId.split("=")[1][0]
        else:
            index = 0
        browseName = f"{index}:{name}"
        parentNode = self.get_node(parentId)

        if value is None:
            node = parentNode.add_folder(nodeId, browseName)
            result = {
                "name": node.get_display_name().to_string(),
                "nodeId": node.nodeid.to_string(),
            }
        else:
            node = parentNode.add_variable(nodeId, browseName, value)
            attribute = node.get_attribute(ua.AttributeIds.Value)
            result = {
                "name": node.get_display_name().to_string(),
                "nodeId": node.nodeid.to_string(),
                "value": attribute.Value.Value,
                "dataType": attribute.Value.VariantType.name,
                "sourceTimestamp": attribute.SourceTimestamp,
                "statusCode": attribute.StatusCode.name
            }

            if writable is True:
                node.set_writable()

        return result

    def delete_node(self, nodeId, recursive=True):
        """
        Recursively deletes node and it's subnodes unless recursive=False.
        Requires admins.
        Doesn't raise errors if deleting is unsuccessful.
        """

        self.check_connection()
        node = self.get_node(nodeId)
        result = self.client.delete_nodes([node], recursive)
        result[1][0].check()
        return result[1][0].is_good()

    async def read(self, params):
        """
        Reads from OPC UA server
        params == ua.ReadParameters() that are properly set up.

        Returns result object and time it took to read from OPC UA server.
        """

        self.check_connection()
        start = time.time_ns()
        result = self.client.uaclient.read(params)
        readTime = time.time_ns() - start
        return result, readTime

    async def write(self, params):
        """
        Writes to OPC UA server
        params == ua.WriteParameters() that are properly set up.

        Returns result object and time it took to read from OPC UA server.
        """

        self.check_connection()
        start = time.time_ns()
        result = self.client.uaclient.write(params)
        writeTime = time.time_ns() - start
        return result, writeTime

    def variant_type_finder(self, value, nodeId):
        """
        Attempts to find variant type of given value.
        If not found, retrieves variant type of node from OPC UA server.
        """

        valueType = type(value)
        if isinstance(valueType, datetime.datetime):
            variantType = ua.uatypes.VariantType.DateTime
        elif valueType == bool:
            variantType = ua.uatypes.VariantType.Boolean
        elif valueType == str:
            variantType = ua.uatypes.VariantType.String
        elif valueType == int or valueType == float:
            node = self.get_node(nodeId)
            self.check_connection()
            variantType = node.get_data_type_as_variant_type()
        else:
            raise ValueError("Unsupported datatype")
        return variantType
Beispiel #47
0
class OPCUAClient:
    def __init__(self,
                 server: str,
                 username='',
                 password='',
                 reconnect_interval=1000):
        self.server = server
        self.username = username
        self.password = password

        self.client = Client(self.server)
        self.client.set_user(username)
        self.client.set_password(password)

        self.connection_status = False
        self.connectivity_thread = None
        self.reconnect_interval = reconnect_interval
        self.connected_once = False

        self.stop_flag = False
        self.stopped = True

    def connect(self):
        self.connectivity_thread = threading.Thread(
            target=self.__connectivity_routine)
        self.stopped = False
        self.connectivity_thread.start()
        sleep(1)

    def disconnect(self):
        logging.info('Disconnecting to OPC UA server %s ...' % self.server)
        self.stop_flag = True
        self.client.disconnect()
        while not self.stopped:
            sleep(0.1)
            logging.info('Disconnected from OPC UA server %s' % self.server)

    def __single_connect(self):
        logging.info('Connecting to OPC UA server %s ...' % self.server)
        try:
            self.client.connect()
            logging.info('Connection to OPC UA server %s established' %
                         self.server)
            sleep(1)
            self.connected_once = True
        except Exception as exc:
            logging.warning('Connection to OPC UA server %s failed' %
                            self.server,
                            exc_info=exc)

    def __connectivity_routine(self):
        while True:
            if self.stop_flag:
                self.stopped = True
                return
            self.check_connection()
            if not self.connection_status:
                self.__single_connect()
            sleep(self.reconnect_interval / 1000)

    def check_connection(self):
        logging.debug('Checking connection status to OPCA UA server %s ...' %
                      self.server)
        try:
            self.client.get_node(ua.NodeId(2259, 0)).get_data_value()
            logging.debug('Connection to OPCA UA server %s persists' %
                          self.server)
            self.connection_status = True
        except Exception as exc:
            logging.warning(
                'Connection to OPCA UA server %s does NOT persist' %
                self.server)
            self.connection_status = False
            sleep(1)

    def get_connection_status(self):
        return self.connection_status

    def get_url(self):
        return self.server

    def get_server_obj(self):
        return self.client
Beispiel #48
0
def uacall():
    parser = argparse.ArgumentParser(description="Call method of a node")
    add_common_args(parser)
    parser.add_argument(
        "-m",
        "--method",
        dest="method",
        type=int,
        default=None,
        help=
        "Set method to call. If not given then (single) method of the selected node is used."
    )
    parser.add_argument("-M",
                        "--method-name",
                        dest="method_name",
                        type=str,
                        default=None,
                        help="Set name of method to call. Overrides --method")
    parser.add_argument("-l",
                        "--list",
                        "--array",
                        dest="array",
                        default="guess",
                        choices=["guess", "true", "false"],
                        help="Value is an array")
    parser.add_argument("-t",
                        "--datatype",
                        dest="datatype",
                        default="guess",
                        choices=[
                            "guess", 'byte', 'sbyte', 'nodeid',
                            'expandednodeid', 'qualifiedname', 'browsename',
                            'string', 'float', 'double', 'int16', 'int32',
                            "int64", 'uint16', 'uint32', 'uint64', "bool",
                            "string", 'datetime', 'bytestring', 'xmlelement',
                            'statuscode', 'localizedtext'
                        ],
                        help="Data type to return")
    parser.add_argument("value",
                        help="Value to use for call to method, if any",
                        nargs="?",
                        metavar="VALUE")

    args = parse_args(parser, requirenodeid=True)

    client = Client(args.url, timeout=args.timeout)
    _configure_client_with_args(client, args)
    client.connect()
    try:
        node = get_node(client, args)
        # val must be a tuple in order to enable method calls without arguments
        if (args.value is None):
            val = ()  #empty tuple
        else:
            val = (_val_to_variant(args.value, args),
                   )  # tuple with one element

        # determine method to call: Either explicitly given or automatically select the method of the selected node.
        methods = node.get_methods()
        method_id = None
        #print( "methods=%s" % (methods) )

        if (args.method_name is not None):
            method_id = args.method_name
        elif (args.method is None):
            if (len(methods) == 0):
                raise ValueError(
                    "No methods in selected node and no method given")
            elif (len(methods) == 1):
                method_id = methods[0]
            else:
                raise ValueError(
                    "Selected node has {0:d} methods but no method given. Provide one of {1!s}"
                    .format(*(methods)))
        else:
            for m in methods:
                if (m.nodeid.Identifier == args.method):
                    method_id = m.nodeid
                    break

        if (method_id is None):
            # last resort:
            method_id = ua.NodeId(
                identifier=args.method)  #, namespaceidx=? )#, nodeidtype=?): )

        #print( "method_id=%s\nval=%s" % (method_id,val) )

        result_variants = node.call_method(method_id, *val)
        print("resulting result_variants={0!s}".format(result_variants))
    finally:
        client.disconnect()
    sys.exit(0)
    print(args)
Beispiel #49
0
    def datachange_notification(self, node, val, data):
        try:

            logger.debug(
                "handler: New data change event on fhs server: NewValAvailable=%s",
                val)

            # GET SOME VALUES FROM THIS SERVER
            logger.debug("handler: connecting to DTZ master Server")
            this_client = Client("opc.tcp://0.0.0.0:4840/freeopcua/server")
            this_client.connect()
            this_client_root = this_client.get_root_node()
            self.demonstrator_busy = this_client_root.get_child(
                ["0:Objects", "2:DTZMasterController", "2:DemonstratorBusy"])

            # GET SOME VALUES FROM FHS SERVER
            logger.debug("handler: connecting to FHS Server")
            # handler_client_fhs = Client(global_url_pseudo_fhs_server)                                                  # Testing with pseudo FH server
            handler_client_fhs = Client(global_url_fhs_server)  # Original
            handler_client_fhs.connect()
            handler_root_fhs = handler_client_fhs.get_root_node()
            # handler_desired_shelf = handler_client_fhs.get_node("ns=2;i=3")                                            # Testing with pseudo FH server
            handler_desired_shelf = handler_client_fhs.get_node(
                "ns=6;s=::AsGlobalPV:ShelfNumber")  # Original

            # GET VALUES FROM PANDA SERVER
            logger.debug("handler: connecting to Panda Server")
            handler_client_panda = Client(global_url_panda_server)
            handler_client_panda.connect()
            handler_root_panda = handler_client_panda.get_root_node()
            self.handler_panda_moving = handler_root_panda.get_child(
                ["0:Objects", "2:PandaRobot", "2:RobotMoving"])

            # GET VALUES FROM PIXTEND SERVER
            logger.debug("handler: connecting to Pixtend Server")
            handler_client_pixtend = Client(global_url_pixtend_server)
            handler_client_pixtend.connect()
            handler_root_pixtend = handler_client_pixtend.get_root_node()
            self.handler_belt_moving = handler_root_pixtend.get_child(
                ["0:Objects", "2:ConveyorBelt", "2:ConBeltMoving"])

            # data = NewValueAvailable
            demoBusy = self.demonstrator_busy.get_value()
            exit = "NewValAvailable is {}, demonstratorBusy is {}".format(
                val, demoBusy)

            if val is True and demoBusy is False:
                logger.debug("handler: global_demonstrator_busy: " +
                             str(demoBusy) + ". NewValAvailable: " + str(val) +
                             ". ShelfNumber: " +
                             str(handler_desired_shelf.get_value()) + ".")

                ############# LOAD STORAGE DATA  #############
                # [1][2][3]
                # [4][5][6]
                # [7][8][9]

                with open("./dtz_storage", "r", encoding="utf-8") as in_file:
                    for in_line in in_file:
                        self.storage.append(in_line)

                # IS THE STORAGE EMPTY?
                self.storage[handler_desired_shelf.get_value() - 1] = "1"

                #if self.storage[handler_desired_shelf.get_value() - 1] is "0":   # commented because of problems with demonstrator
                if False:
                    exit = "Shelf empty - error!"
                else:
                    self.demonstrator_busy.set_value(True)

                    # METHOD CALLS
                    move_panda_thread = threading.Thread(
                        name='move_panda_thread',
                        target=self.move_robot_core,
                        args=(
                            "SO",
                            handler_desired_shelf.get_value(),
                        ))
                    move_panda_thread.daemon = True
                    move_panda_thread.start()
                    move_panda_thread.join()

                    # logger.debug("p_moved %s", self.panda_moved)
                    if self.panda_moved is True:
                        move_belt_thread = threading.Thread(
                            name='move_belt_thread',
                            target=self.move_belt_core,
                            args=(
                                "left",
                                0.55,
                            ))
                        move_belt_thread.daemon = True
                        move_belt_thread.start()
                        self.storage[handler_desired_shelf.get_value() -
                                     1] = "0"
                        move_belt_thread.join()
                        if not self.belt_moved:
                            logger.debug("Error - Belt not moved")
                            exit = "Error - Belt not moved"
                    else:
                        logger.debug("Error - Panda not moved")
                        exit = "Error - Panda not moved"

                    ############# SAVE STORAGE DATA  #############
                    # [1][2][3]
                    # [4][5][6]
                    # [7][8][9]
                    with open("./dtz_storage", "w",
                              encoding="utf-8") as out_file:
                        for out_line in self.storage:
                            out_file.write(str(out_line))

            logger.debug("handler: disconnect from fhs server")
            handler_client_fhs.disconnect()
            logger.debug("handler: disconnect from panda server")
            handler_client_panda.disconnect()
            logger.debug("handler: disconnect from pixtend server")
            handler_client_pixtend.disconnect()
            this_client.disconnect()

        except Exception as e:
            logger.debug("handler: Catched Exception: " + str(e))
            try:
                logger.debug(
                    "handler: trying to disconnect from pixtend server")
                handler_client_pixtend.disconnect()
            except:
                logger.debug("handler: pixtend server was disconnected")
                pass
            try:
                logger.debug("handler: trying to disconnect from panda server")
                handler_client_panda.disconnect()
            except:
                logger.debug("handler: panda server was disconnected")
                pass
            try:
                logger.debug("handler: trying to disconnect from fhs server")
                handler_client_fhs.disconnect()
            except:
                logger.debug("handler: fhs server was disconnected")
                pass
            return "handler: Error: " + str(e)

        logger.debug(
            "handler: exiting datachange_notification. return message: %s",
            exit)
        return exit
Beispiel #50
0
#!usr/bin/env python
#-*- coding:utf-8 _*-
"""
@author:zengguang
@file: client2.py
@time: 2021/2/1 14:05
"""
from opcua import Client, ua
url = "opc.tcp://127.0.0.1:12345/"
# url = "opc.tcp://127.0.0.1:12346/test"
c = Client(url)
try:
    c.connect()
    # root = c.find_servers()
    root = c.get_node('ns=2;i=11').get_value()
    print(root)
    # print("\r\nBrower:")
    # brower_child2(root.get_child(["0:Objects"]), -1, ["Server"])
except Exception as e:
    print("Client Exception:", e)
finally:
    c.disconnect()
class OpcUaConnector(Thread, Connector):
    def __init__(self, gateway, config, connector_type):
        self.__connector_type = connector_type
        self.statistics = {'MessagesReceived': 0,
                           'MessagesSent': 0}
        super().__init__()
        self.__gateway = gateway
        self.__server_conf = config.get("server")
        self.__interest_nodes = []
        self.__available_object_resources = {}
        for mapping in self.__server_conf["mapping"]:
            if mapping.get("deviceNodePattern") is not None:
                self.__interest_nodes.append({mapping["deviceNodePattern"]: mapping})
            else:
                log.error("deviceNodePattern in mapping: %s - not found, add property deviceNodePattern to processing this mapping",
                          dumps(mapping))
        if "opc.tcp" not in self.__server_conf.get("url"):
            opcua_url = "opc.tcp://"+self.__server_conf.get("url")
        else:
            opcua_url = self.__server_conf.get("url")
        self.client = Client(opcua_url, timeout=self.__server_conf.get("timeoutInMillis", 4000)/1000)
        if self.__server_conf["identity"]["type"] == "cert.PEM":
            try:
                ca_cert = self.__server_conf["identity"].get("caCert")
                private_key = self.__server_conf["identity"].get("privateKey")
                cert = self.__server_conf["identity"].get("cert")
                security_mode = self.__server_conf["identity"].get("mode", "SignAndEncrypt")
                policy = self.__server_conf["security"]
                if cert is None or private_key is None:
                    log.exception("Error in ssl configuration - cert or privateKey parameter not found")
                    raise
                security_string = policy+','+security_mode+','+cert+','+private_key
                if ca_cert is not None:
                    security_string = security_string + ',' + ca_cert
                self.client.set_security_string(security_string)

            except Exception as e:
                log.exception(e)
        if self.__server_conf["identity"].get("username"):
            self.client.set_user(self.__server_conf["identity"].get("username"))
            if self.__server_conf["identity"].get("password"):
                self.client.set_password(self.__server_conf["identity"].get("password"))

        self.setName(self.__server_conf.get("name", 'OPC-UA Default ' + ''.join(choice(ascii_lowercase) for _ in range(5))) + " Connector")
        self.__opcua_nodes = {}
        self._subscribed = {}
        self.data_to_send = []
        self.__sub_handler = SubHandler(self)
        self.__stopped = False
        self.__connected = False
        self.daemon = True

    def is_connected(self):
        return self.__connected

    def open(self):
        self.__stopped = False
        self.start()
        log.info("Starting OPC-UA Connector")

    def run(self):
        while not self.__connected:
            try:
                self.__connected = self.client.connect()
                self.client.load_type_definitions()
            except ConnectionRefusedError:
                log.error("Connection refused on connection to OPC-UA server with url %s", self.__server_conf.get("url"))
                time.sleep(10)
            except Exception as e:
                log.debug("error on connection to OPC-UA server.")
                log.error(e)
                time.sleep(10)
            else:
                self.__connected = True
                log.info("OPC-UA connector %s connected to server %s", self.get_name(), self.__server_conf.get("url"))
        self.__opcua_nodes["root"] = self.client.get_root_node()
        self.__opcua_nodes["objects"] = self.client.get_objects_node()
        sub = self.client.create_subscription(self.__server_conf.get("scanPeriodInMillis", 500), self.__sub_handler)
        self.__search_name(self.__opcua_nodes["objects"], 2)
        self.__search_tags(self.__opcua_nodes["objects"], 2, sub)
        log.debug('Subscriptions: %s', self.subscribed)
        log.debug("Available methods: %s", self.__available_object_resources)
        while True:
            try:
                time.sleep(1)
                if self.data_to_send:
                    self.__gateway.send_to_storage(self.get_name(), self.data_to_send.pop())
                if self.__stopped:
                    break
            except (KeyboardInterrupt, SystemExit):
                self.close()
                raise
            except Exception as e:
                self.close()
                log.exception(e)

    def close(self):
        self.__stopped = True
        self.client.disconnect()
        self.__connected = False
        log.info('%s has been stopped.', self.get_name())

    def get_name(self):
        return self.name

    def on_attributes_update(self, content):
        log.debug(content)
        try:
            for server_variables in self.__available_object_resources[content["device"]]['variables']:
                for attribute in content["data"]:
                    for variable in server_variables:
                        if attribute == variable:
                            server_variables[variable].set_value(content["data"][variable])
        except Exception as e:
            log.exception(e)

    def server_side_rpc_handler(self, content):
        try:
            for method in self.__available_object_resources['methods'][content["device"]]:
                rpc_method = content["data"].get("method")
                if rpc_method is not None and method.get(rpc_method) is not None:
                    arguments = content["data"].get("params")
                    if type(arguments) is list:
                        result = method["node"].call_method(method[rpc_method], *arguments)
                    elif arguments is not None:
                        result = method["node"].call_method(method[rpc_method], arguments)
                    else:
                        result = method["node"].call_method(method[rpc_method])

                    self.__gateway.send_rpc_reply(content["device"],
                                                  content["data"]["id"],
                                                  {content["data"]["method"]: result})

                    log.debug("method %s result is: %s", method[rpc_method], result)
        except Exception as e:
            log.exception(e)

    def __search_name(self, node, recursion_level):
        try:
            for childId in node.get_children():
                ch = self.client.get_node(childId)
                current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True))
                if self.__interest_nodes:
                    if ch.get_node_class() == ua.NodeClass.Object:
                        for interest_node in self.__interest_nodes:
                            for int_node in interest_node:
                                if re.search(int_node.split('\\.')[recursion_level-2], ch.get_display_name().Text):
                                    self.__search_name(ch, recursion_level+1)
                    elif ch.get_node_class() == ua.NodeClass.Variable:
                        try:
                            for interest_node in self.__interest_nodes:
                                for int_node in interest_node:
                                    if interest_node[int_node].get("deviceName") is None:
                                        try:
                                            name_pattern = TBUtility.get_value(interest_node[int_node]["deviceNamePattern"],
                                                                               get_tag=True)
                                            device_name_node = re.search(name_pattern.split('.')[-1], current_var_path)
                                            if device_name_node is not None:
                                                device_name = ch.get_value()
                                                full_device_name = interest_node[int_node]["deviceNamePattern"].replace("${"+name_pattern+"}",
                                                                                                                        device_name)
                                                interest_node[int_node]["deviceName"] = full_device_name
                                                if self.__available_object_resources.get(full_device_name) is None:
                                                    self.__available_object_resources[full_device_name] = {'methods': [],
                                                                                                           'variables': []}
                                                if not self.__gateway.get_devices().get(full_device_name):
                                                    self.__gateway.add_device(full_device_name, {"connector": None})
                                                self.__gateway.update_device(full_device_name, "connector", self)
                                        except Exception as e:
                                            log.exception(e)
                        except BadWaitingForInitialData:
                            pass
                elif not self.__interest_nodes:
                    log.error("Nodes in mapping not found, check your settings.")
        except Exception as e:
            log.exception(e)

    def __search_tags(self, node, recursion_level, sub=None):
        try:
            for childId in node.get_children():
                ch = self.client.get_node(childId)
                current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True))
                if self.__interest_nodes:
                    if ch.get_node_class() == ua.NodeClass.Object:
                        for interest_node in self.__interest_nodes:
                            for int_node in interest_node:
                                if re.search(int_node.split('\\.')[recursion_level-2], ch.get_display_name().Text):
                                    try:
                                        methods = ch.get_methods()
                                        for method in methods:
                                            self.__available_object_resources[interest_node[int_node]["deviceName"]]["methods"].append({method.get_display_name().Text: method,
                                                                                                                                       "node": ch})
                                    except Exception as e:
                                        log.exception(e)
                                    self.__search_tags(ch, recursion_level+1, sub)
                    elif ch.get_node_class() == ua.NodeClass.Variable:
                        try:
                            for interest_node in self.__interest_nodes:
                                for int_node in interest_node:
                                    if interest_node[int_node].get("attributes_updates"):
                                        try:
                                            for attribute_update in interest_node[int_node]["attributes_updates"]:
                                                if attribute_update["attributeOnDevice"] == ch.get_display_name().Text:
                                                    self.__available_object_resources[interest_node[int_node]["deviceName"]]['variables'].append({attribute_update["attributeOnThingsBoard"]: ch, })
                                        except Exception as e:
                                            log.exception(e)
                                    if re.search(int_node.replace('$', ''), current_var_path):
                                        tags = []
                                        if interest_node[int_node].get("attributes"):
                                            tags.extend(interest_node[int_node]["attributes"])
                                        if interest_node[int_node].get("timeseries"):
                                            tags.extend(interest_node[int_node]["timeseries"])
                                        for tag in tags:
                                            target = TBUtility.get_value(tag["path"], get_tag=True)
                                            if ch.get_display_name().Text == target:
                                                sub.subscribe_data_change(ch)
                                                if interest_node[int_node].get("uplink_converter") is None:
                                                    if interest_node[int_node].get('converter') is None:
                                                        converter = OpcUaUplinkConverter(interest_node[int_node])
                                                    else:
                                                        converter = TBUtility.check_and_import(self.__connector_type, interest_node[int_node]['converter'])
                                                    interest_node[int_node]["uplink_converter"] = converter
                                                else:
                                                    converter = interest_node[int_node]["uplink_converter"]
                                                self.subscribed[ch] = {"converter": converter,
                                                                       "path": current_var_path}
                        except BadWaitingForInitialData:
                            pass
                    elif not self.__interest_nodes:
                        log.error("Nodes in mapping not found, check your settings.")
        except Exception as e:
            log.exception(e)

    @property
    def subscribed(self):
        return self._subscribed
Beispiel #52
0
class PubSubServer:

    def __init__(self, uri, nid_configuration, nid_start_stop, nid_status):
        self.uri = uri
        self.client = Client(self.uri)
        self.client.application_uri = "urn:S2OPC:localhost"
        self.nid_configuration = nid_configuration
        self.nid_start_stop = nid_start_stop
        self.nid_status = nid_status

    # Connect to the Pub/Sub server. Shall be called before other methods
    def connect(self):
        self.client.connect()
        print('Connected')
        self.nodeConfiguration =self.client.get_node(self.nid_configuration)
        self.nodeStartStop = self.client.get_node(self.nid_start_stop)
        self.nodeStatus = self.client.get_node(self.nid_status)
        
    # Is connected to Pub/Sub server
    def isConnected(self):
        try:
            self.nodeStatus.get_value()
            return True
        except:
            return False

    # Disconnect to the Pub/Sub server    
    def disconnect(self):
        self.client.disconnect()
        print('Disconnected')

    def __setStartStop(self, value):
        try:
            # Set value and wait until value changes or timeout expires
            self.nodeStartStop.set_value(ua.Variant(value, ua.VariantType.Byte))
            status = 2 if value else 0
            timeout = PUBSUBSERVER_TIMEOUT_MAX
            while self.getStatus() != status and timeout > 0:
                sleep(PUBSUBSERVER_TIMEOUT_STEP)
                timeout = timeout - PUBSUBSERVER_TIMEOUT_STEP
        except e:
            print('Client not connected to PubSubServer')
            
    # Is Pub/Sub module started
    def isStart(self):
        try:
            return bool(self.nodeStartStop.get_value())
        except:
            print('Client not connected to PubSubServer')
            return False
        
    # Start the Pub/Sub module
    # Wait until status changes or timeout expires
    def start(self):
        self.__setStartStop(1)
        
    # Stop the Pub/Sub module
    # Wait until status changes or timeout expires
    def stop(self):
        self.__setStartStop(0)

    # Get the Pub/Sub module status:
    #  - 0 : not running
    #  - 2 : is running
    def getStatus(self):
        try:
            return self.nodeStatus.get_value()
        except:
            print('Client not connected to PubSubServer')
            return 0
        
    # Set the Pub/Sub module configuration
    # Value is a XML in a string
    def setConfiguration(self, value):
        try:
            self.nodeConfiguration.set_value(ua.Variant(value, ua.VariantType.String))
        except:
            print('Client not connected to PubSubServer')

    # Get the Pub/Sub module configuration as XML string
    def getConfiguration(self):
        try:
            return self.nodeConfiguration.get_value()
        except:
            print('Client not connected to PubSubServer')
            return None

    # Get value. Nid is a string
    def getValue(self, nid):
        node = self.client.get_node(nid)
        return node.get_value()

    # Set value.
    # - nid is a string.
    # - varianttype is a builtintype from ua package
    # - value type depends of varianttype
    def setValue(self, nid, varianttype, value):
        node = self.client.get_node(nid)
        node.set_value(value=value, varianttype=varianttype)
Beispiel #53
0
from opcua import Client
from opcua import ua

# client = Client("opc.tcp://10.19.3.49:49320/AGVkanban.fx3u")
# try:
#     client.connect()
#
# except OSError as e:
#     print(e)
#
# print(client.get_node("ns=2;s=AGVkanban.fx3u." + "7号车当前动作指令").get_value())

client1 = Client("opc.tcp://127.0.0.1:49320")
client1.connect()
client1.disconnect()

try:
    client1.disconnect()
except Exception as e:
    pass

client1.connect()

nodeId = {}
nodeId[1] = 'ns=2;s=shougonghanjieAGVbaojing.FX3U.shougonghanjieAGV'

# 好像拼音写错了
nodeId[2] = 'ns=2;s=jiaobizhuanxiangAGVbaojing.FX3U.jiaobizhuangxiangAGV'
# 好像和 新萨瓦尼尼 1 2 颠倒了
nodeId[3] = 'ns=2;s=sawanini1houdaoAGVbaojing.FX3U.sawanini1houdaoAGV'
nodeId[4] = 'ns=2;s=houbanAGVbaojing.FX3U.houbanAGV'
Beispiel #54
0
class OpcUaConnector(Thread, Connector):
    def __init__(self, gateway, config, connector_type):
        self._connector_type = connector_type
        self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
        super().__init__()
        self.__gateway = gateway
        self.__server_conf = config.get("server")
        self.__interest_nodes = []
        self.__available_object_resources = {}
        self.__show_map = self.__server_conf.get("showMap", False)
        self.__previous_scan_time = 0
        for mapping in self.__server_conf["mapping"]:
            if mapping.get("deviceNodePattern") is not None:
                self.__interest_nodes.append(
                    {mapping["deviceNodePattern"]: mapping})
            else:
                log.error(
                    "deviceNodePattern in mapping: %s - not found, add property deviceNodePattern to processing this mapping",
                    dumps(mapping))
        if "opc.tcp" not in self.__server_conf.get("url"):
            self.__opcua_url = "opc.tcp://" + self.__server_conf.get("url")
        else:
            self.__opcua_url = self.__server_conf.get("url")
        self.client = Client(
            self.__opcua_url,
            timeout=self.__server_conf.get("timeoutInMillis", 4000) / 1000)
        if self.__server_conf["identity"].get("type") == "cert.PEM":
            self.__set_auth_settings_by_cert()
        if self.__server_conf["identity"].get("username"):
            self.__set_auth_settings_by_username()

        self.setName(
            self.__server_conf.get(
                "name", 'OPC-UA ' +
                ''.join(choice(ascii_lowercase)
                        for _ in range(5))) + " Connector")
        self.__opcua_nodes = {}
        self._subscribed = {}
        self.__sub = None
        self.__sub_handler = SubHandler(self)
        self.data_to_send = []
        self.__stopped = False
        self.__connected = False
        self.daemon = True

    def is_connected(self):
        return self.__connected

    def open(self):
        self.__stopped = False
        self.start()
        log.info("Starting OPC-UA Connector")

    def run(self):
        while not self.__connected:
            try:
                self.client.connect()
                try:
                    self.client.load_type_definitions()
                except Exception as e:
                    log.debug(e)
                    log.debug("Error on loading type definitions.")
                log.debug(self.client.get_namespace_array()[-1])
                log.debug(
                    self.client.get_namespace_index(
                        self.client.get_namespace_array()[-1]))
            except ConnectionRefusedError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                time.sleep(10)
            except OSError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                time.sleep(10)
            except Exception as e:
                log.debug("error on connection to OPC-UA server.")
                log.error(e)
                time.sleep(10)
            else:
                self.__connected = True
                log.info("OPC-UA connector %s connected to server %s",
                         self.get_name(), self.__server_conf.get("url"))
        self.__initialize_client()
        while not self.__stopped:
            try:
                time.sleep(.2)
                self.__check_connection()
                if not self.__connected and not self.__stopped:
                    self.client.connect()
                    self.__initialize_client()
                    log.info("Reconnected to the OPC-UA server - %s",
                             self.__server_conf.get("url"))
                elif not self.__stopped:
                    if self.__server_conf.get(
                            "disableSubscriptions", False
                    ) and time.time(
                    ) * 1000 - self.__previous_scan_time > self.__server_conf.get(
                            "scanPeriodInMillis", 60000):
                        self.scan_nodes_from_config()
                        self.__previous_scan_time = time.time() * 1000
                    # giusguerrini, 2020-09-24: Fix: flush event set and send all data to platform,
                    # so data_to_send doesn't grow indefinitely in case of more than one value change
                    # per cycle, and platform doesn't lose events.
                    # NOTE: possible performance improvement: use a map to store only one event per
                    # variable to reduce frequency of messages to platform.
                    while self.data_to_send:
                        self.__gateway.send_to_storage(self.get_name(),
                                                       self.data_to_send.pop())
                if self.__stopped:
                    self.close()
                    break
            except (KeyboardInterrupt, SystemExit):
                self.close()
                raise
            except FuturesTimeoutError:
                self.__check_connection()
            except Exception as e:
                log.error(
                    "Connection failed on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                log.exception(e)

                self.client = Client(
                    self.__opcua_url,
                    timeout=self.__server_conf.get("timeoutInMillis", 4000) /
                    1000)
                if self.__server_conf["identity"].get("type") == "cert.PEM":
                    self.__set_auth_settings_by_cert()
                if self.__server_conf["identity"].get("username"):
                    self.__set_auth_settings_by_username()

                self._subscribed = {}
                self.__available_object_resources = {}
                time.sleep(10)

    def __set_auth_settings_by_cert(self):
        try:
            ca_cert = self.__server_conf["identity"].get("caCert")
            private_key = self.__server_conf["identity"].get("privateKey")
            cert = self.__server_conf["identity"].get("cert")
            security_mode = self.__server_conf["identity"].get(
                "mode", "SignAndEncrypt")
            policy = self.__server_conf["security"]
            if cert is None or private_key is None:
                log.exception(
                    "Error in ssl configuration - cert or privateKey parameter not found"
                )
                raise RuntimeError(
                    "Error in ssl configuration - cert or privateKey parameter not found"
                )
            security_string = policy + ',' + security_mode + ',' + cert + ',' + private_key
            if ca_cert is not None:
                security_string = security_string + ',' + ca_cert
            self.client.set_security_string(security_string)

        except Exception as e:
            log.exception(e)

    def __set_auth_settings_by_username(self):
        self.client.set_user(self.__server_conf["identity"].get("username"))
        if self.__server_conf["identity"].get("password"):
            self.client.set_password(
                self.__server_conf["identity"].get("password"))

    def __check_connection(self):
        try:
            node = self.client.get_root_node()
            node.get_children()
            if not self.__server_conf.get("disableSubscriptions", False) and (
                    not self.__connected or not self.subscribed):
                self.__sub = self.client.create_subscription(
                    self.__server_conf.get("subCheckPeriodInMillis", 500),
                    self.__sub_handler)
            self.__connected = True
        except ConnectionRefusedError:
            self.__connected = False
            self._subscribed = {}
            self.__available_object_resources = {}
            self.__sub = None
        except OSError:
            self.__connected = False
            self._subscribed = {}
            self.__available_object_resources = {}
            self.__sub = None
        except FuturesTimeoutError:
            self.__connected = False
            self._subscribed = {}
            self.__available_object_resources = {}
            self.__sub = None
        except AttributeError:
            self.__connected = False
            self._subscribed = {}
            self.__available_object_resources = {}
            self.__sub = None
        except Exception as e:
            self.__connected = False
            self._subscribed = {}
            self.__available_object_resources = {}
            self.__sub = None
            log.exception(e)

    def close(self):
        self.__stopped = True
        if self.__connected:
            self.client.disconnect()
        self.__connected = False
        log.info('%s has been stopped.', self.get_name())

    def get_name(self):
        return self.name

    def on_attributes_update(self, content):
        log.debug(content)
        try:
            for server_variables in self.__available_object_resources[
                    content["device"]]['variables']:
                for attribute in content["data"]:
                    for variable in server_variables:
                        if attribute == variable:
                            try:
                                server_variables[variable].set_value(
                                    content["data"][variable])
                            except Exception:
                                server_variables[variable].set_attribute(
                                    ua.AttributeIds.Value,
                                    ua.DataValue(content["data"][variable]))
        except Exception as e:
            log.exception(e)

    def server_side_rpc_handler(self, content):
        try:
            rpc_method = content["data"].get("method")

            # firstly check if a method is not service
            if rpc_method == 'set' or rpc_method == 'get':
                full_path = ''
                args_list = []
                try:
                    args_list = content['data']['params'].split(';')

                    if 'ns' in content['data']['params']:
                        full_path = ';'.join([
                            item for item in (args_list[0:-1] if rpc_method ==
                                              'set' else args_list)
                        ])
                    else:
                        full_path = args_list[0].split('=')[-1]
                except IndexError:
                    log.error('Not enough arguments. Expected min 2.')
                    self.__gateway.send_rpc_reply(
                        content['device'], content['data']['id'], {
                            content['data']['method']:
                            'Not enough arguments. Expected min 2.',
                            'code': 400
                        })

                node_list = []
                self.__search_node(current_node=content['device'],
                                   fullpath=full_path,
                                   result=node_list)

                node = None
                try:
                    node = node_list[0]
                except IndexError:
                    self.__gateway.send_rpc_reply(
                        content['device'], content['data']['id'], {
                            content['data']['method']: 'Node didn\'t find!',
                            'code': 500
                        })

                if rpc_method == 'get':
                    self.__gateway.send_rpc_reply(
                        content['device'], content['data']['id'], {
                            content['data']['method']: node.get_value(),
                            'code': 200
                        })
                else:
                    try:
                        value = args_list[2].split('=')[-1]
                        node.set_value(value)
                        self.__gateway.send_rpc_reply(content['device'],
                                                      content['data']['id'], {
                                                          'success': 'true',
                                                          'code': 200
                                                      })
                    except ValueError:
                        log.error('Method SET take three arguments!')
                        self.__gateway.send_rpc_reply(
                            content['device'], content['data']['id'], {
                                'error': 'Method SET take three arguments!',
                                'code': 400
                            })
                    except ua.UaStatusCodeError:
                        log.error('Write method doesn\'t allow!')
                        self.__gateway.send_rpc_reply(
                            content['device'], content['data']['id'], {
                                'error': 'Write method doesn\'t allow!',
                                'code': 400
                            })

            for method in self.__available_object_resources[
                    content["device"]]['methods']:
                if rpc_method is not None and method.get(
                        rpc_method) is not None:
                    arguments_from_config = method["arguments"]
                    arguments = content["data"].get(
                        "params") if content["data"].get(
                            "params") is not None else arguments_from_config
                    try:
                        if isinstance(arguments, list):
                            result = method["node"].call_method(
                                method[rpc_method], *arguments)
                        elif arguments is not None:
                            try:
                                result = method["node"].call_method(
                                    method[rpc_method], arguments)
                            except ua.UaStatusCodeError as e:
                                if "BadTypeMismatch" in str(e) and isinstance(
                                        arguments, int):
                                    result = method["node"].call_method(
                                        method[rpc_method], float(arguments))
                        else:
                            result = method["node"].call_method(
                                method[rpc_method])

                        self.__gateway.send_rpc_reply(
                            content["device"], content["data"]["id"], {
                                content["data"]["method"]: result,
                                "code": 200
                            })
                        log.debug("method %s result is: %s",
                                  method[rpc_method], result)
                    except Exception as e:
                        log.exception(e)
                        self.__gateway.send_rpc_reply(content["device"],
                                                      content["data"]["id"], {
                                                          "error": str(e),
                                                          "code": 500
                                                      })
                else:
                    log.error("Method %s not found for device %s", rpc_method,
                              content["device"])
                    self.__gateway.send_rpc_reply(
                        content["device"], content["data"]["id"], {
                            "error": "%s - Method not found" % (rpc_method),
                            "code": 404
                        })
        except Exception as e:
            log.exception(e)

    def __initialize_client(self):
        self.__opcua_nodes["root"] = self.client.get_objects_node()
        self.__opcua_nodes["objects"] = self.client.get_objects_node()
        self.scan_nodes_from_config()
        self.__previous_scan_time = time.time() * 1000
        log.debug('Subscriptions: %s', self.subscribed)
        log.debug("Available methods: %s", self.__available_object_resources)

    def scan_nodes_from_config(self):
        try:
            if self.__interest_nodes:
                for device_object in self.__interest_nodes:
                    for current_device in device_object:
                        try:
                            device_configuration = device_object[
                                current_device]
                            devices_info_array = self.__search_general_info(
                                device_configuration)
                            for device_info in devices_info_array:
                                if device_info is not None and device_info.get(
                                        "deviceNode") is not None:
                                    self.__search_nodes_and_subscribe(
                                        device_info)
                                    self.__save_methods(device_info)
                                    self.__search_attribute_update_variables(
                                        device_info)
                                else:
                                    log.error(
                                        "Device node is None, please check your configuration."
                                    )
                                    log.debug(
                                        "Current device node is: %s",
                                        str(
                                            device_configuration.get(
                                                "deviceNodePattern")))
                                    break
                        except BrokenPipeError:
                            log.debug("Broken Pipe. Connection lost.")
                        except OSError:
                            log.debug("Stop on scanning.")
                        except FuturesTimeoutError:
                            self.__check_connection()
                        except Exception as e:
                            log.exception(e)
                log.debug(self.__interest_nodes)
        except Exception as e:
            log.exception(e)

    def __search_nodes_and_subscribe(self, device_info):
        sub_nodes = []
        information_types = {
            "attributes": "attributes",
            "timeseries": "telemetry"
        }
        for information_type in information_types:
            for information in device_info["configuration"][information_type]:
                information_key = information["key"]
                config_path = TBUtility.get_value(information["path"],
                                                  get_tag=True)
                information_path = self._check_path(config_path,
                                                    device_info["deviceNode"])
                information["path"] = '${%s}' % information_path
                information_nodes = []
                self.__search_node(device_info["deviceNode"],
                                   information_path,
                                   result=information_nodes)
                for information_node in information_nodes:
                    if information_node is not None:
                        try:
                            information_value = information_node.get_value()
                        except:
                            log.error("Err get_value: %s",
                                      str(information_node))
                            continue
                        log.debug(
                            "Node for %s \"%s\" with path: %s - FOUND! Current values is: %s",
                            information_type, information_key,
                            information_path, str(information_value))
                        if device_info.get("uplink_converter") is None:
                            configuration = {
                                **device_info["configuration"], "deviceName":
                                device_info["deviceName"],
                                "deviceType":
                                device_info["deviceType"]
                            }
                            if device_info["configuration"].get(
                                    'converter') is None:
                                converter = OpcUaUplinkConverter(configuration)
                            else:
                                converter = TBModuleLoader.import_module(
                                    self._connector_type, configuration)
                            device_info["uplink_converter"] = converter
                        else:
                            converter = device_info["uplink_converter"]
                        self.subscribed[information_node] = {
                            "converter": converter,
                            "path": information_path,
                            "config_path": config_path
                        }
                        if not device_info.get(
                                information_types[information_type]):
                            device_info[
                                information_types[information_type]] = []
                        converted_data = converter.convert(
                            (config_path, information_path), information_value)
                        self.statistics['MessagesReceived'] = self.statistics[
                            'MessagesReceived'] + 1
                        self.data_to_send.append(converted_data)
                        self.statistics['MessagesSent'] = self.statistics[
                            'MessagesSent'] + 1
                        log.debug("Data to ThingsBoard: %s", converted_data)
                        if not self.__server_conf.get("disableSubscriptions",
                                                      False):
                            sub_nodes.append(information_node)
                    else:
                        log.error(
                            "Node for %s \"%s\" with path %s - NOT FOUND!",
                            information_type, information_key,
                            information_path)
        if not self.__server_conf.get("disableSubscriptions", False):
            if self.__sub is None:
                self.__sub = self.client.create_subscription(
                    self.__server_conf.get("subCheckPeriodInMillis", 500),
                    self.__sub_handler)
            if sub_nodes:
                self.__sub.subscribe_data_change(sub_nodes)
                log.debug("Added subscription to nodes: %s", str(sub_nodes))

    def __save_methods(self, device_info):
        try:
            if self.__available_object_resources.get(
                    device_info["deviceName"]) is None:
                self.__available_object_resources[
                    device_info["deviceName"]] = {}
            if self.__available_object_resources[
                    device_info["deviceName"]].get("methods") is None:
                self.__available_object_resources[
                    device_info["deviceName"]]["methods"] = []
            if device_info["configuration"].get("rpc_methods", []):
                node = device_info["deviceNode"]
                for method_object in device_info["configuration"][
                        "rpc_methods"]:
                    method_node_path = self._check_path(
                        method_object["method"], node)
                    methods = []
                    self.__search_node(node,
                                       method_node_path,
                                       True,
                                       result=methods)
                    for method in methods:
                        if method is not None:
                            node_method_name = method.get_display_name().Text
                            self.__available_object_resources[
                                device_info["deviceName"]]["methods"].append({
                                    node_method_name:
                                    method,
                                    "node":
                                    node,
                                    "arguments":
                                    method_object.get("arguments")
                                })
                        else:
                            log.error(
                                "Node for method with path %s - NOT FOUND!",
                                method_node_path)
        except Exception as e:
            log.exception(e)

    def __search_attribute_update_variables(self, device_info):
        try:
            if device_info["configuration"].get("attributes_updates", []):
                node = device_info["deviceNode"]
                device_name = device_info["deviceName"]
                if self.__available_object_resources.get(device_name) is None:
                    self.__available_object_resources[device_name] = {}
                if self.__available_object_resources[device_name].get(
                        "variables") is None:
                    self.__available_object_resources[device_name][
                        "variables"] = []
                for attribute_update in device_info["configuration"][
                        "attributes_updates"]:
                    attribute_path = self._check_path(
                        attribute_update["attributeOnDevice"], node)
                    attribute_nodes = []
                    self.__search_node(node,
                                       attribute_path,
                                       result=attribute_nodes)
                    for attribute_node in attribute_nodes:
                        if attribute_node is not None:
                            if self.get_node_path(
                                    attribute_node) == attribute_path:
                                self.__available_object_resources[device_name][
                                    "variables"].append({
                                        attribute_update["attributeOnThingsBoard"]:
                                        attribute_node
                                    })
                        else:
                            log.error(
                                "Attribute update node with path \"%s\" - NOT FOUND!",
                                attribute_path)
        except Exception as e:
            log.exception(e)

    def __search_general_info(self, device):
        result = []
        match_devices = []
        self.__search_node(self.__opcua_nodes["root"],
                           TBUtility.get_value(device["deviceNodePattern"],
                                               get_tag=True),
                           result=match_devices)
        for device_node in match_devices:
            if device_node is not None:
                result_device_dict = {
                    "deviceName": None,
                    "deviceType": None,
                    "deviceNode": device_node,
                    "configuration": deepcopy(device)
                }
                name_pattern_config = device["deviceNamePattern"]
                name_expression = TBUtility.get_value(name_pattern_config,
                                                      get_tag=True)
                if "${" in name_pattern_config and "}" in name_pattern_config:
                    log.debug("Looking for device name")
                    device_name_from_node = ""
                    if name_expression == "$DisplayName":
                        device_name_from_node = device_node.get_display_name(
                        ).Text
                    elif name_expression == "$BrowseName":
                        device_name_from_node = device_node.get_browse_name(
                        ).Name
                    elif name_expression == "$NodeId.Identifier":
                        device_name_from_node = str(
                            device_node.nodeid.Identifier)
                    else:
                        name_path = self._check_path(name_expression,
                                                     device_node)
                        device_name_node = []
                        self.__search_node(device_node,
                                           name_path,
                                           result=device_name_node)
                        if len(device_name_node) == 0:
                            log.warn(
                                "Device name node - not found, skipping device..."
                            )
                            continue
                        device_name_node = device_name_node[0]
                        if device_name_node is not None:
                            device_name_from_node = device_name_node.get_value(
                            )
                    if device_name_from_node == "":
                        log.error(
                            "Device name node not found with expression: %s",
                            name_expression)
                        return None
                    full_device_name = name_pattern_config.replace(
                        "${" + name_expression + "}",
                        str(device_name_from_node)).replace(
                            name_expression, str(device_name_from_node))
                else:
                    full_device_name = name_expression
                result_device_dict["deviceName"] = full_device_name
                log.debug("Device name: %s", full_device_name)
                if device.get("deviceTypePattern"):
                    device_type_expression = TBUtility.get_value(
                        device["deviceTypePattern"], get_tag=True)
                    if "${" in device_type_expression and "}" in device_type_expression:
                        type_path = self._check_path(device_type_expression,
                                                     device_node)
                        device_type_node = []
                        self.__search_node(device_node,
                                           type_path,
                                           result=device_type_node)
                        device_type_node = device_type_node[0]
                        if device_type_node is not None:
                            device_type = device_type_node.get_value()
                            full_device_type = device_type_expression.replace(
                                "${" + device_type_expression + "}",
                                device_type).replace(device_type_expression,
                                                     device_type)
                        else:
                            log.error(
                                "Device type node not found with expression: %s",
                                device_type_expression)
                            full_device_type = "default"
                    else:
                        full_device_type = device_type_expression
                    result_device_dict["deviceType"] = full_device_type
                    log.debug("Device type: %s", full_device_type)
                else:
                    result_device_dict["deviceType"] = "default"
                result.append(result_device_dict)
            else:
                log.error(
                    "Device node not found with expression: %s",
                    TBUtility.get_value(device["deviceNodePattern"],
                                        get_tag=True))
        return result

    @cached(cache=TTLCache(maxsize=1000, ttl=10 * 60))
    def get_node_path(self, node: Node):
        return '\\.'.join(node.get_browse_name().Name
                          for node in node.get_path(200000))

    def __search_node(self,
                      current_node,
                      fullpath,
                      search_method=False,
                      result=None):
        if result is None:
            result = []
        try:
            if regex.match(r"ns=\d*;[isgb]=.*", fullpath, regex.IGNORECASE):
                if self.__show_map:
                    log.debug("Looking for node with config")
                node = self.client.get_node(fullpath)
                if node is None:
                    log.warning("NODE NOT FOUND - using configuration %s",
                                fullpath)
                else:
                    log.debug("Found in %s", node)
                    result.append(node)
            else:
                fullpath_pattern = regex.compile(fullpath)
                full1 = fullpath.replace('\\\\.', '.')
                # current_node_path = '\\.'.join(char.split(":")[1] for char in current_node.get_path(200000, True))
                current_node_path = self.get_node_path(current_node)
                # we are allways the parent
                child_node_parent_class = current_node.get_node_class()
                new_parent = current_node
                for child_node in current_node.get_children():
                    new_node_class = child_node.get_node_class()
                    # this will not change you can do it outside th loop
                    # basis Description of node.get_parent() function, sometime child_node.get_parent() return None
                    # new_parent = child_node.get_parent()
                    # if (new_parent is None):
                    #    child_node_parent_class = current_node.get_node_class()
                    # else:
                    #    child_node_parent_class = child_node.get_parent().get_node_class()
                    # current_node_path = '\\.'.join(char.split(":")[1] for char in current_node.get_path(200000, True))
                    # new_node_path = '\\\\.'.join(char.split(":")[1] for char in child_node.get_path(200000, True))
                    new_node_path = self.get_node_path(child_node)
                    if child_node_parent_class == ua.NodeClass.View and new_parent is not None:
                        parent_path = self.get_node_path(new_parent)
                        # parent_path = '\\.'.join(char.split(":")[1] for char in new_parent.get_path(200000, True))
                        fullpath = fullpath.replace(current_node_path,
                                                    parent_path)
                    nnp1 = new_node_path.replace('\\\\.', '.')
                    nnp2 = new_node_path.replace('\\\\', '\\')
                    if self.__show_map:
                        log.debug("SHOW MAP: Current node path: %s",
                                  new_node_path)
                    regex_fullmatch = regex.fullmatch(fullpath_pattern, nnp1) or \
                                      nnp2 == full1 or \
                                      nnp2 == fullpath or \
                                      nnp1 == full1
                    if regex_fullmatch:
                        if self.__show_map:
                            log.debug(
                                "SHOW MAP: Current node path: %s - NODE FOUND",
                                nnp2)
                        result.append(child_node)
                    else:
                        regex_search = fullpath_pattern.fullmatch(nnp1, partial=True) or \
                                       nnp2 in full1 or \
                                       nnp1 in full1
                        if regex_search:
                            if self.__show_map:
                                log.debug(
                                    "SHOW MAP: Current node path: %s - NODE FOUND",
                                    new_node_path)
                            if new_node_class == ua.NodeClass.Object:
                                if self.__show_map:
                                    log.debug("SHOW MAP: Search in %s",
                                              new_node_path)
                                self.__search_node(child_node,
                                                   fullpath,
                                                   result=result)
                            elif new_node_class == ua.NodeClass.Variable:
                                log.debug("Found in %s", new_node_path)
                                result.append(child_node)
                            elif new_node_class == ua.NodeClass.Method and search_method:
                                log.debug("Found in %s", new_node_path)
                                result.append(child_node)
        except CancelledError:
            log.error(
                "Request during search has been canceled by the OPC-UA server."
            )
        except BrokenPipeError:
            log.error("Broken Pipe. Connection lost.")
        except OSError:
            log.debug("Stop on scanning.")
        except Exception as e:
            log.exception(e)

    def _check_path(self, config_path, node):
        if regex.match(r"ns=\d*;[isgb]=.*", config_path, regex.IGNORECASE):
            return config_path
        if re.search(r"^root", config_path.lower()) is None:
            node_path = self.get_node_path(node)
            # node_path = '\\\\.'.join(char.split(":")[1] for char in node.get_path(200000, True))
            if config_path[-3:] != '\\.':
                information_path = (node_path + '\\.' + config_path).replace(
                    '\\', '\\\\')
            else:
                information_path = node_path + config_path.replace(
                    '\\', '\\\\')
        else:
            information_path = config_path
        result = information_path[:]
        return result

    @property
    def subscribed(self):
        return self._subscribed
Beispiel #55
0
def run():
    logger.info("Modular Input mi_opcua command: %s" % sys.argv)
    if len(sys.argv) > 1:
        try:
            if sys.argv[1] == "--scheme":
                do_scheme()
            elif sys.argv[1] == "--validate-arguments":
                validate_arguments()
            elif sys.argv[1] == "--test":
                test()
            else:
                usage()
        except Exception as ex:
            logger.critical(ex)
    else:
        logger.info("Modular Input mi_opcua Starts data collection.")

        configs = get_config()
        stanza = configs["name"]
        patterns = configs["measures"].split(":")
        tout = configs["connection_timeout"].strip()
        spec = configs.get("metrics_spec", "n.a.").strip()
        timeout = 1 if len(tout) <= 0 else int(tout)

        conn = configs[
            "connection"]  ## "opc.tcp://ec2-54-190-162-94.us-west-2.compute.amazonaws.com:49320"

        if configs.has_key("username"):
            username = configs["username"].strip()
            if len(username) > 0:
                password = configs["password"].strip()
                conn = "%s?username=%s&password=%s" % (conn, username,
                                                       password)

        client = Client(conn, timeout=timeout)

        mi.init_stream(sys.stdout)
        try:
            logger.info("Start connecting OPC Server [%s]." % conn)
            client.connect()
            logger.info("OPC Server [%s] is connected." % conn)
            measures = []
            root = client.get_root_node()

            node.collect_measures(measures, patterns, root)

            md = {}
            try:
                jm = os.path.join(ua.data_dir(), spec)
                with open(jm, 'r') as mfp:
                    md = json.load(mfp)
                    mfp.close()
            except:
                pass

            for m in measures:
                collect_data(stanza, m[len(m) - 1], spec=md)

        except Exception as ex:
            logger.critical(ex)
        finally:
            mi.fini_stream(sys.stdout)
            logger.info("---- end of opc ua ----")
            client.disconnect()
Beispiel #56
0
#!/usr/bin/env python3
import time
import datetime
from opcua import Client

remoteIO1url = "opc.tcp://*****:*****@192.168.0.51:4840"
remoteIO2url = "opc.tcp://*****:*****@192.168.0.52:4840"

remoteIO1 = Client(remoteIO1url)
remoteIO2 = Client(remoteIO2url)

remoteIO1.connect()
remoteIO2.connect()
print("Client Connected")

orders = 2

# Define the process values
IO1input1value = False  # Punching machine
IO1input2value = False
IO1output1value = False
IO1output2value = False
IO2input1value = False  # Conveyor belt
IO2input2value = False
IO2output1value = False
IO2output2value = False

# Define the OPC-UA nodes
IO1input1 = remoteIO1.get_node("ns=1;s=Read Input 1.")
IO1input2 = remoteIO1.get_node("ns=1;s=Read Input 2.")
IO1output1 = remoteIO1.get_node("ns=1;s=Control Output 1.")
Beispiel #57
0
class OpcUaClient(object):
    CONNECT_TIMEOUT = 15  # [sec]
    RETRY_DELAY = 10  # [sec]
    MAX_RETRIES = 3  # [-]

    class Decorators(object):
        @staticmethod
        def autoConnectingClient(wrappedMethod):
            def wrapper(obj, *args, **kwargs):
                for retry in range(OpcUaClient.MAX_RETRIES):
                    try:
                        return wrappedMethod(obj, *args, **kwargs)
                    except ua.uaerrors.BadNoMatch:
                        raise
                    except Exception:
                        pass
                    try:
                        obj._logger.warn('(Re)connecting to OPC-UA service.')
                        obj.reconnect()
                    except ConnectionRefusedError:
                        obj._logger.warn(
                            'Connection refused. Retry in 10s.'.format(
                                OpcUaClient.RETRY_DELAY))
                        time.sleep(OpcUaClient.RETRY_DELAY)
                else:  # So the exception is exposed.
                    obj.reconnect()
                    return wrappedMethod(obj, *args, **kwargs)

            return wrapper

    def __init__(self, serverUrl):
        self._logger = logging.getLogger(self.__class__.__name__)
        self._client = Client(serverUrl.geturl(), timeout=self.CONNECT_TIMEOUT)

    def __enter__(self):
        self.connect()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.disconnect()
        self._client = None

    @property
    @Decorators.autoConnectingClient
    def sensorList(self):
        return self.objectsNode.get_children()

    @property
    @Decorators.autoConnectingClient
    def objectsNode(self):
        path = [ua.QualifiedName(name='Objects', namespaceidx=0)]
        return self._client.get_root_node().get_child(path)

    def connect(self):
        self._client.connect()
        self._client.load_type_definitions()

    def disconnect(self):
        try:
            self._client.disconnect()
        except Exception:
            pass

    def reconnect(self):
        self.disconnect()
        self.connect()

    @Decorators.autoConnectingClient
    def get_browse_name(self, uaNode):
        return uaNode.get_browse_name()

    @Decorators.autoConnectingClient
    def get_node_class(self, uaNode):
        return uaNode.get_node_class()

    @Decorators.autoConnectingClient
    def get_child(self, uaNode, path):
        return uaNode.get_child(path)

    @Decorators.autoConnectingClient
    def read_raw_history(self,
                         uaNode,
                         starttime=None,
                         endtime=None,
                         numvalues=0,
                         cont=None):
        details = ua.ReadRawModifiedDetails()
        details.IsReadModified = False
        details.StartTime = starttime or ua.get_win_epoch()
        details.EndTime = endtime or ua.get_win_epoch()
        details.NumValuesPerNode = numvalues
        details.ReturnBounds = True
        result = OpcUaClient._history_read(uaNode, details, cont)
        assert (result.StatusCode.is_good())
        return result.HistoryData.DataValues, result.ContinuationPoint

    @staticmethod
    def _history_read(uaNode, details, cont):
        valueid = ua.HistoryReadValueId()
        valueid.NodeId = uaNode.nodeid
        valueid.IndexRange = ''
        valueid.ContinuationPoint = cont

        params = ua.HistoryReadParameters()
        params.HistoryReadDetails = details
        params.TimestampsToReturn = ua.TimestampsToReturn.Both
        params.ReleaseContinuationPoints = False
        params.NodesToRead.append(valueid)
        result = uaNode.server.history_read(params)[0]
        return result
Beispiel #58
0
elevator_opc_info = {
    'ep_url': "opc.tcp://IntersectWinPC:4840/elevator/pid/",
    'uri': "http://thaintersect.com",
}
nx_server_info = {
    "ep_url": "opc.tcp://localhost:4940/nx/pid/",
    "name": "Elevator_OPC_to_NX",
    "uri": "localhost"
}

if __name__ == "__main__":

    Elevator_client = Client(elevator_opc_info['ep_url'])

    try:
        Elevator_client.connect()
    except Exception as identifier:
        print("Failed to connect to the OPC Server")
        print(identifier)
    else:
        print("Conected to: ", elevator_opc_info['ep_url'])
        # Elevator_client.load_type_definitions()

    disp_c = Elevator_client.get_node("ns=2;i=3")
    aspd_c = Elevator_client.get_node("ns=2;i=4")
    lspd_c = Elevator_client.get_node("ns=2;i=5")
    up_c = Elevator_client.get_node("ns=2;i=7")

    nx_server = Server()
    nx_server.set_endpoint(nx_server_info['ep_url'])
    nx_server.set_server_name(nx_server_info['name'])
    """

    def data_change(self, handle, node, val, attr):
        print("Python: New data change event", handle, node, val, attr)

    def event(self, handle, event):
        print("Python: New event", handle, event)


if __name__ == "__main__":
    #from IPython import embed
    logging.basicConfig(level=logging.WARN)
    client = Client("opc.tcp://*****:*****@localhost:53530/OPCUA/SimulationServer/")
    try:
        client.connect()
        root = client.get_root_node()
        print("Root is", root)
        print("childs of root are: ", root.get_children())
        print("name of root is", root.get_browse_name())
        objects = client.get_objects_node()
        print("childs og objects are: ", objects.get_children())
        myfloat = client.get_node("ns=4;s=Float")
        mydouble = client.get_node("ns=4;s=Double")
        myint64 = client.get_node("ns=4;s=Int64")
        myuint64 = client.get_node("ns=4;s=UInt64")
        myint32 = client.get_node("ns=4;s=Int32")
        myuint32 = client.get_node("ns=4;s=UInt32")

        var = client.get_node(ua.NodeId("Random1", 5))
        print("var is: ", var)
Beispiel #60
0
        '--path',
        type=str,
        help='path for storing tool data. Default is in ./tools',
        default="./tools")

    args = parser.parse_args()

    if args.verbose:
        logger.setLevel(level=logging.DEBUG)

    try:
        url = re.sub(r"\/\/",
                     "//" + args.opcua_user + ":" + args.opcua_password + "@",
                     args.opcua_connection)
        opcua_client = Client(url)  #connect using a user
        opcua_client.connect()
        logger.info('Successfully connceted to OPC UA server: %s',
                    [args.opcua_connection])
    except Exception as e:
        logger.error('Failed connecting to OPC UA server: %s',
                     [args.opcua_connection])
        logger.debug(traceback.format_exc())
        sys.exit(str(e))

    try:
        #get max number of tools
        TnumWZV = opcua_client.get_node(ua.NodeId("/Tool/Catalogue/TnumWZV",
                                                  2)).get_value()
        logger.info('Number of available tools: {}'.format(TnumWZV))
        numCuttEdgeParams = args.numCuttEdgeParams