Example #1
0
async def main():
    server = Server()
    await server.init()
    server.set_endpoint('opc.tcp://192.168.0.100:4840/opcua/')
    server.set_server_name("OPC-UA Server")

    uri = 'http://devnetiot.com/opcua/'
    idx = await server.register_namespace(uri)

    obj_plc = await server.nodes.objects.add_object(idx, 'PLC')
    var_temperature = await obj_plc.add_variable(idx, 'temperature', 0)
    var_humidity = await obj_plc.add_variable(idx, 'humidity', 0)

    _logger.info('Starting server!')
    async with server:
        while True:
            humidity, temperature = Adafruit_DHT.read_retry(
                Adafruit_DHT.DHT11, DHT_DATA_PIN)

            if humidity is not None and temperature is not None:
                print('temperature: {0:0.1f}*C'.format(temperature))
                print('humidity: {0:0.1f}%'.format(humidity))
                await var_temperature.write_value(float(temperature))
                await var_humidity.write_value(float(humidity))
            else:
                print('Failed to get DHT11 reading, trying again in ',
                      DHT_READ_TIMEOUT, 'seconds')

            await asyncio.sleep(DHT_READ_TIMEOUT)
Example #2
0
class DemoServer:
    def __init__(self):
        self.server = Server()

        self.server.set_endpoint('opc.tcp://0.0.0.0:51210/UA/SampleServer')
        self.server.set_server_name('Custom structure demo server')
        # idx name will be used later for creating the xml used in data type dictionary
        self._idx_name = 'http://examples.freeopcua.github.io'
        self.idx = self.server.register_namespace(self._idx_name)

        self.dict_builder = DataTypeDictionaryBuilder(self.server, self.idx,
                                                      self._idx_name,
                                                      'MyDictionary')

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        quit()

    def start_server(self):
        self.server.start()

    def create_structure(self, name):
        # save the created data type
        return self.dict_builder.create_data_type(name)

    def complete_creation(self):
        self.dict_builder.set_dict_byte_string()
Example #3
0
async def main():
    global rpm_is
    
    puls.when_pressed = callback_rpm # set callback
    
    # initialize Server
    server = Server()
    await server.init()
    server.set_endpoint('opc.tcp://pi.local:4840/freeopcua/server/')
    server.set_server_name("OPC UA Raspi Server")
    # all possible endpoint policies set for client connection
    server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign])
    
    # setup namespace
    uri = "example-uri.edu"
    idx = await server.register_namespace(uri)
    
    # create Motor-node type for later use
    base_motor = await motor_object(idx, server)


    # populateing address space
    motor = await server.nodes.objects.add_object(idx, "Motor", base_motor)
    rpm_var = await motor.get_child([f"{idx}:RPM"]) # rounds per minute
    await rpm_var.set_writable()
    speed_var = await motor.get_child([f"{idx}:Speed"]) # motor speed
    await speed_var.set_writable()
    
    # Start!
    async with server:
        while True:
            rpm_is, speed_is = await asyncio.gather(*(get_rpm(rpm_var), set_speed(speed_var)))
Example #4
0
class HelloServer:
    def __init__(self, endpoint, name, model_filepath):
        self.server = Server()

        #  This need to be imported at the start or else it will overwrite the data
        self.server.import_xml(model_filepath)

        self.server.set_endpoint(endpoint)
        self.server.set_server_name(name)

        objects = self.server.get_objects_node()

        freeopcua_namespace = self.server.get_namespace_index(
            "urn:freeopcua:python:server")
        hellower = objects.get_child("0:Hellower")
        hellower_say_hello = hellower.get_child("0:SayHello")

        self.server.link_method(hellower_say_hello, say_hello_xml)

        hellower.add_method(freeopcua_namespace, "SayHello2", say_hello,
                            [ua.VariantType.Boolean], [ua.VariantType.String])

        hellower.add_method(freeopcua_namespace, "SayHelloArray",
                            say_hello_array, [ua.VariantType.Boolean],
                            [ua.VariantType.String])

    def __enter__(self):
        self.server.start()
        return self.server

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.server.stop()
Example #5
0
class TestServer:
    def __init__(self):
        " Basic setup of server"
        # async def __init__ doesn't work
        self.server = Server()
        self.idx = None
        self.top = None
        self.vars = []

    async def create_simulator(self):
        await self.server.init()
        self.server.set_endpoint(f'opc.tcp://{LOCAL_HOST}:{PORT}/{PATH}')
        self.server.set_server_name("OPC-UA Test Server")
        uri = "https://github.com/it-hms/my-opcua-test-server"
        self.idx = await self.server.register_namespace(uri)
        self.top = await self.server.nodes.objects.add_object(
            self.idx, 'Dynamic')
        for i in range(MAX_TAG + 1):
            t_var = await self.top.add_variable(self.idx, f"Random.Float{i}",
                                                0)
            self.vars.append(t_var)

    async def run(self):
        async with self.server:
            while True:
                i = 0
                for var in self.vars:
                    await var.write_value(random.gauss(i * 10, 9))
                    i += 1
                await asyncio.sleep(2)
Example #6
0
async def main():
    # Certificates folder
    certs_folder = os.environ.get('CERTS_FOLDER', os.path.dirname(os.path.realpath(__file__)))
    key_pem_path = os.path.join(certs_folder, "key.pem")
    cert_der_path = os.path.join(certs_folder, "certificate.der")

    server = Server()
    await server.init()
    await server.set_application_uri("urn:opcua:iom:server")
    server.set_endpoint('opc.tcp://0.0.0.0:4840/freeopcua/server/')
    server.set_server_name("IoM PLC Server Example")

    # Security
    await server.load_certificate(cert_der_path)
    await server.load_private_key(key_pem_path)
    server.set_security_policy([
                ua.SecurityPolicyType.NoSecurity,
                ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt])

    # setup our own namespace, not really necessary but should as spec
    idx = await server.register_namespace("https://tknika.eus/opcua/demo/plc")
    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()
    # populating our address space
    plc_server = await objects.add_object(idx, 'PLC Server')

    bool_data = await plc_server.add_variable(idx, 'BooleanData', True, datatype=ua.NodeId(1, 0))
    pos_data = await plc_server.add_variable(idx, 'PositiveTrendData', 0, datatype=ua.NodeId(11, 0))
    neg_data = await plc_server.add_variable(idx, 'NegativeTrendData', 0, datatype=ua.NodeId(11, 0))
    temp_data = await plc_server.add_variable(idx, 'TemperatureData', 18.5, datatype=ua.NodeId(11, 0))
    hum_data = await plc_server.add_variable(idx, 'HumidityData', 60.2, datatype=ua.NodeId(11, 0))
    cyc_data = await plc_server.add_variable(idx, 'CyclicData', 0, datatype=ua.NodeId(11, 0))
    mirror_orig_data = await plc_server.add_variable(idx, 'MirrorDataOriginal', True, datatype=ua.NodeId(1, 0))
    mirror_copy_data = await plc_server.add_variable(idx, 'MirrorDataCopy', True, datatype=ua.NodeId(1, 0))
    latitude_data = await plc_server.add_variable(idx, "GPSLatitude", "", datatype=ua.NodeId(12, 0))
    longitude_data = await plc_server.add_variable(idx, "GPSLongitude", "", datatype=ua.NodeId(12, 0))
    latitude_longitude_data = await plc_server.add_variable(idx, "GPSLatitudeAndLongitude", "", datatype=ua.NodeId(12, 0))

    logger.info('Starting OPC UA server!')

    bool_task = asyncio.Task(toggle_data(bool_data, refresh=10, init=True))
    pos_task = asyncio.Task(periodic_data(pos_data, refresh=5))
    neg_task = asyncio.Task(periodic_data(neg_data, refresh=5, increment=-2))
    temp_task = asyncio.Task(random_data(temp_data, refresh=10, init=18.5, min=15, max=22))
    hum_task = asyncio.Task(random_data(hum_data, refresh=10, init=60.2, min=0, max=100))
    cyclic_task = asyncio.Task(cyclic_data(cyc_data, cycle_time=200, step=0.5, init=0, min=-100, max=100))
    
    mirror_handler = MirrorHandler(server, mirror_orig_data, mirror_copy_data)
    await mirror_handler.start()

    tcx_update_handler = TCXUpdateHandler("circular-urnieta-aia-donosti-urnieta.tcx", latitude_data, longitude_data, latitude_longitude_data)
    tcx_task = asyncio.Task(tcx_update_handler.start())

    async with server:
        await asyncio.gather(bool_task, pos_task, neg_task, temp_task, hum_task, cyclic_task, tcx_task)
Example #7
0
async def main():
    # optional: setup logging
    logging.basicConfig(level=logging.WARN)
    #logger = logging.getLogger("asyncua.address_space")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.internal_server")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.uaprocessor")
    # logger.setLevel(logging.DEBUG)
    logger = logging.getLogger("asyncua.subscription_service")
    logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    await server.init()
    #await server.disable_clock()
    #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")

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

    # get Objects node, this is where we should put our custom stuff
    objects = server.nodes.objects

    # populating our address space
    myfolder = await objects.add_folder(idx, "myEmptyFolder")
    myobj = await objects.add_object(idx, "MyObject")
    myvar = await myobj.add_variable(idx, "MyVariable", 6.7)
    await myvar.set_writable()  # Set MyVariable to be writable by clients

    # starting!
    await server.start()

    # Create Callback for item event
    server.subscribe_server_callback(CallbackType.ItemSubscriptionCreated,
                                     create_monitored_items)
    server.subscribe_server_callback(CallbackType.ItemSubscriptionModified,
                                     modify_monitored_items)
    server.subscribe_server_callback(CallbackType.ItemSubscriptionDeleted,
                                     delete_monitored_items)

    while True:
        await asyncio.sleep(1)
Example #8
0
async def start_servers():
    """ Spin up two servers with identical configurations """
    ports = [4840, 4841]
    urls = []
    loop = asyncio.get_event_loop()
    for port in ports:
        server = Server()
        await server.init()
        url = f"opc.tcp://0.0.0.0:{port}/freeopcua/server/"
        urls.append(url)
        server.set_endpoint(url)
        server.set_server_name("FreeOpcUa Example Server {port}")
        # setup our own namespace
        uri = "http://examples.freeopcua.github.io"
        idx = await server.register_namespace(uri)

        myobj = await server.nodes.objects.add_object(idx, "MyObject")
        myvar = await myobj.add_variable(idx, "MyVariable", 6.7)
        await server.start()
        loop.create_task(server_var_update(server, myvar))
    return urls, myvar
Example #9
0
async def main():
    # Create Server
    server = Server()
    await server.init()

    # Set server configuration
    server.set_endpoint(_opc_ua_server)
    server.set_server_name(_opc_ua_server_name)
    server.set_security_policy([
        ua.SecurityPolicyType.NoSecurity,
        ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
        ua.SecurityPolicyType.Basic256Sha256_Sign
    ])

    # Set namespace
    idx = await server.register_namespace(_opc_ua_namespace)

    # Create Sensor object with two properties
    sensor = await server.nodes.base_object_type.add_object_type(idx, "Sensor")
    await (await sensor.add_variable(idx, "value",
                                     0.0)).set_modelling_rule(True)

    # Populate the address space
    sensor0 = await server.nodes.objects.add_object(idx, "Sensor0", sensor)
    await (await sensor0.add_property(idx, "id", 0)).set_modelling_rule(True)
    await (await sensor0.add_property(idx, "name",
                                      "Sensor0")).set_modelling_rule(True)

    # Start Server
    async with server:
        # Retrieve Sensor0 value variable, in order to read/write it
        sensor0_value_var = await sensor0.get_child([f"{idx}:value"])

        while True:
            # Generate a random float between 0.0 and 100.0
            sensor0_value = uniform(0.0, 100.0)
            # Write the value to trigger data change
            await sensor0_value_var.write_value(sensor0_value)
            # Wait 5 seconds before triggering next event
            await asyncio.sleep(5)
Example #10
0
async def main():
    # setup our server
    server = Server()
    await server.init()
    server.set_endpoint('opc.tcp://127.0.0.1:4840/opcua/')
    server.set_server_name("DevNet OPC-UA Test Server")

    # setup our own namespace, not really necessary but should as spec
    uri = 'http://devnetiot.com/opcua/'
    idx = await server.register_namespace(uri)

    # populating our address space
    # server.nodes, contains links to very common nodes like objects and root
    obj_vplc = await server.nodes.objects.add_object(idx, 'vPLC1')
    var_temperature = await obj_vplc.add_variable(idx, 'temperature', 0)
    var_pressure = await obj_vplc.add_variable(idx, 'pressure', 0)
    var_pumpsetting = await obj_vplc.add_variable(idx, 'pumpsetting', 0)

    # Read Sensor Data from Kaggle
    df = pd.read_csv("sensor.csv")
    # Only use sensor data from 03 and 01 (preference)
    sensor_data = pd.concat([df["sensor_03"], df["sensor_01"]], axis=1)

    _logger.info('Starting server!')
    async with server:
        # run forever and iterate over the dataframe
        while True:
            for row in sensor_data.itertuples():
                # if below the mean use different setting - just for testing
                if row[1] < df["sensor_03"].mean():
                    setting = "standard"
                else:
                    setting = "speed"

                # Writing Variables
                await var_temperature.write_value(float(row[1]))
                await var_pressure.write_value(float(row[2]))
                await var_pumpsetting.write_value(str(setting))
                await asyncio.sleep(1)
Example #11
0
async def main():
    _logger = logging.getLogger('Server')
    #logger = logging.getLogger("asyncua.address_space")
    #logger = logging.getLogger("asyncua.internal_server")
    #logger = logging.getLogger("asyncua.binary_server_asyncio")
    #logger = logging.getLogger("asyncua.uaprocessor")

    server = Server()
    await server.init()
    server.set_endpoint("opc.tcp://0.0.0.0:16703/")
    server.set_server_name("Servidor OPC eMPC MA")
    await server.set_application_uri(uri="http://servidor-eMPC-MA.com/test/")
    server.set_security_policy([ua.SecurityPolicyType.NoSecurity])
    server._permission_ruleset = None
    server._policyIDs = ["Anonymous"]
    server.certificate = None

    uri = "Servidor OPC eMPC MA"
    idx = await server.register_namespace(uri)

    await server.import_xml("deck_opcua.xml")
    _logger.info("Iniciando servidor OPC-UA...")
    _logger.info("Escuchando en: opc.tcp://localhost:16703/")
    # Crear instancia del controlador
    controlador = clase_MPC.Controlador()
    # starting!
    async with server:
        while True:
            await asyncio.sleep(0.01)
            command_run = await server.get_node("ns=6;s=command_run"
                                                ).get_value()
            if command_run == 1:
                _logger.info(
                    f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t Node read: command_run = {command_run}'
                )
                _logger.info(
                    f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t Executing...'
                )
                await controlador.recibir_variables(server)
                controlador.actualizar_arrays()
                ControlFlag = await server.get_node("ns=4;s=ControlFlag"
                                                    ).read_value()
                _logger.info(
                    f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t Node read: Control_Flag = {ControlFlag}'
                )

                if ControlFlag:
                    controlador.ejecutar()
                    await server.write_attribute_value(
                        server.get_node("ns=4;s=uq[1]").nodeid,
                        ua.DataValue(controlador.uq1))
                    _logger.info(
                        f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t \
                                    Node written: uq1 = {controlador.uq1:.3f}')
                    await server.write_attribute_value(
                        server.get_node("ns=4;s=uFr[1]").nodeid,
                        ua.DataValue(controlador.uFr1))
                    _logger.info(
                        f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t \
                                    Node written: uFr1 = {controlador.uFr1:.3f}'
                    )
                    # Falta escribir todas las variables del controlador al servidor
                    await controlador.escribir_variables(server)
                await server.write_attribute_value(
                    server.get_node("ns=6;s=command_run").nodeid,
                    ua.DataValue(0))
                _logger.info(
                    f' [{datetime.now().strftime("%H:%M:%S.%f")[:-3]}]\t Node written: command_run = 0'
                )
Example #12
0
async def main():
    # optional: setup logging
    logging.basicConfig(level=logging.WARN)
    # logger = logging.getLogger("asyncua.address_space")
    # logger.setLevel(logging.DEBUG)
    # logger = logging.getLogger("asyncua.internal_server")
    # logger.setLevel(logging.DEBUG)
    # logger = logging.getLogger("asyncua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    # logger = logging.getLogger("asyncua.uaprocessor")
    # logger.setLevel(logging.DEBUG)
    # logger = logging.getLogger("asyncua.subscription_service")
    # logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    await server.init()
    # server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")

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

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

    # populating our address space
    await objects.add_folder(idx, "myEmptyFolder")
    myobj = await objects.add_object(idx, "MyObject")
    myvar = await myobj.add_variable(idx, "MyVariable", 6.7)
    await myvar.set_writable()  # Set MyVariable to be writable by clients
    myarrayvar = await myobj.add_variable(idx, "myarrayvar", [6.7, 7.9])
    await myobj.add_variable(idx, "myStronglytTypedVariable",
                             ua.Variant([], ua.VariantType.UInt32))
    await myobj.add_property(idx, "myproperty", "I am a property")
    await myobj.add_method(idx, "mymethod", func, [ua.VariantType.Int64],
                           [ua.VariantType.Boolean])

    inargx = ua.Argument()
    inargx.Name = "x"
    inargx.DataType = ua.NodeId(ua.ObjectIds.Int64)
    inargx.ValueRank = -1
    inargx.ArrayDimensions = []
    inargx.Description = ua.LocalizedText("First number x")
    inargy = ua.Argument()
    inargy.Name = "y"
    inargy.DataType = ua.NodeId(ua.ObjectIds.Int64)
    inargy.ValueRank = -1
    inargy.ArrayDimensions = []
    inargy.Description = ua.LocalizedText("Second number y")
    outarg = ua.Argument()
    outarg.Name = "Result"
    outarg.DataType = ua.NodeId(ua.ObjectIds.Int64)
    outarg.ValueRank = -1
    outarg.ArrayDimensions = []
    outarg.Description = ua.LocalizedText("Multiplication result")

    await myobj.add_method(idx, "multiply", multiply, [inargx, inargy],
                           [outarg])
    await myobj.add_method(idx, "multiply_async", multiply_async,
                           [inargx, inargy], [])
    await myobj.add_method(idx, "func_async", func_async,
                           [ua.VariantType.Int64], [])

    async with server:
        while True:
            await asyncio.sleep(1)
Example #13
0
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.internal_server")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.uaprocessor")
    # logger.setLevel(logging.DEBUG)
    logger = logging.getLogger("asyncua.subscription_service")
    logger.setLevel(logging.DEBUG)

    # now setup our server
    server = Server()
    #server.disable_clock()
    #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    server.set_server_name("FreeOpcUa Example Server")

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

    # get Objects node, this is where we should put our custom stuff
    objects = server.nodes.objects

    # populating our address space
    myfolder = objects.add_folder(idx, "myEmptyFolder")
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()  # Set MyVariable to be writable by clients

    # starting!
Example #14
0
    async def start(self):

      node_obj = {}
      variable_obj = {}

      # Data Type Mappings (OPCUA Datatypes to IoT Central Datatypes)
      variant_type = VariantType(self.logger)
      
      # OPCUA Server Setup
      # Here we setup the Server and add discovery
      try:

        # configure the endpoint
        opc_url = self.config["ServerUrlPattern"].format(ip = self.config["IPAddress"], port = self.config["Port"])
        
        if not self.whatif:
          
          # init the server
          opc_server = Server()
          await opc_server.init()
          
          # set the endpoint and name
          opc_server.set_endpoint(opc_url)
          opc_server.set_server_name(self.config["ServerDiscoveryName"])
          
          # set discovery
          await opc_server.set_application_uri(self.config["ApplicationUri"])

        log_msg = "[SERVER CONFIG] ENDPOINT: {ep} APPLICATION URI: {au} APPLICATION NAME: {an}"
        self.logger.info(log_msg.format(ep = opc_url, au = self.config["ApplicationUri"], an = self.config["ServerDiscoveryName"]))

        # Setup root for Map Telemetry
        self.map_telemetry = self.create_map_telemetry(self.config["NameSpace"], self.config["DeviceCapabilityModelId"])

      except Exception as ex:
        self.logger.error("[ERROR] %s" % ex)
        self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup" )
        return

      # OPCUA Server Setup Nodes
      # Here we setup the Nodes and Variables
      try:

        # Set NameSpace
        namespace = self.config["NameSpace"]
        self.logger.info("[NAMESPACE] %s" % namespace)
        
        if not self.whatif:
          id_namespace = await opc_server.register_namespace(namespace)

        node_count = 0

        # Create our Nodes and Parameters
        for node in self.nodes:

          # Add Node and Begin Populating our Address Space
          if not self.whatif:
            
            # Create Node
            node_obj[node["Name"]] = await opc_server.nodes.objects.add_object(id_namespace, node["Name"])
            self.logger.info("[NODE ID] %s" % node_obj[node["Name"]])
            
            # Setup nodes for Map Telemetry
            self.map_telemetry["Nodes"].append(self.create_map_telemetry_node(node["Name"], str(node_obj[node["Name"]]), node["InterfacelId"], node["InterfaceInstanceName"]))

          for variable in node["Variables"]:
            
            variable_name = variable["DisplayName"]
            telemetry_name = variable["TelemetryName"]
            range_value = variable["RangeValues"][0]
            opc_variant_type = variant_type.map_variant_type(variable["IoTCDataType"])
            log_msg = "[SETUP VARIABLE] NODE NAME: {nn} DISPLAY NAME: {dn} TELEMETRY NAME: {tn} RANGE VALUE: {rv} " \
              "IoTC TYPE: {it} OPC VARIANT TYPE {ovt} OPC DATA TYPE {odt}"
            self.logger.info(log_msg.format(nn = node["Name"], dn = variable["DisplayName"], vn = variable["TelemetryName"], \
              tn = variable["TelemetryName"], rv = variable["RangeValues"][0], it = variable["IoTCDataType"], \
                ovt = opc_variant_type, odt = opc_variant_type))

            if not self.whatif:
              
              # Create Node Variable
              nodeObject = await node_obj[node["Name"]].add_variable(id_namespace, telemetry_name, range_value)
              await nodeObject.set_writable()
              variable_obj[telemetry_name] = nodeObject
              self.map_telemetry_nodes_variables.append(self.create_map_telemetry_variable(variable_name, telemetry_name, str(variable_obj[telemetry_name]), variable["IoTCDataType"]))

          if not self.whatif:
            self.map_telemetry["Nodes"][node_count]["Variables"] = copy.copy(self.map_telemetry_nodes_variables)
            self.logger.info("[MAP] %s" % self.map_telemetry)
            self.map_telemetry_nodes_variables =  []
          
          node_count += 1

        if not self.whatif:
          self.update_map_telemetry()
            
      except Exception as ex:
        self.logger.error("[ERROR] %s" % ex)
        self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup for the Nodes and Variables" )
        return
      
      # Start the server and save the address space
      try:
        
        if not self.whatif and self.cache_addr_space == "save":
          filename = Path(self.config["CacheAddrSpaceFileName"])
          opc_server.start()
          opc_server.iserver.dump_address_space(filename)
          opc_server.stop()
          self.logger.info("[CACHE ADDRESS SPACE] Saved and Server Terminated. Now run with -c load")
          return

      except Exception as ex:
          self.logger.error("[ERROR] %s" % ex)
          self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup for the Nodes and Variables" )
          return

      # We start the server loop if we are not in WhatIf and the CacheAddrSpace
      # is null (not set) or load. If it was load, we pulled it from the cache on
      # server init()...
      if not self.whatif and (self.cache_addr_space == None or self.cache_addr_space == "load"):
        
        self.logger.info("[STARTING SERVER] %s" % opc_url)
        
        if self.cache_addr_space == "load":
          filename = Path(self.config["CacheAddrSpaceFileName"])
          opc_server.iserver.load_address_space(filename)
          self.logger.info("[CACHE ADDRESS SPACE] Loaded Address Space Cache from %s" % filename)

        opc_server.start()

        async with opc_server:
          while True:
            await asyncio.sleep(self.config["ServerFrequencyInSeconds"])
            for node in self.nodes:
              temp_dict = self.nodes_dict[node["Name"]]
              temp_dict_counter = self.nodes_dict_counter[node["Name"]]
              
              for variable in node["Variables"]:
                count = temp_dict_counter[variable["TelemetryName"]]
                sequence_count = temp_dict[variable["TelemetryName"]]

                if count > (sequence_count - 1):
                  count = 0              

                # Choose the next value in the telemetry sequence for the variable
                self.nodes_dict_counter[node["Name"]][variable["TelemetryName"]] = (count + 1)
                value = variable["RangeValues"][count]
                
                if not self.whatif:
                  await variable_obj[variable["TelemetryName"]].write_value(value)
                
                log_msg = "[LOOP] {nn} {tn} {vw} {tc} SEQ({sc}) CUR({cc})"
                self.logger.info(log_msg.format(nn = node["Name"], tn = variable["TelemetryName"], vw = value, tc = count, sc = temp_dict[variable["TelemetryName"]], cc = temp_dict_counter[variable["TelemetryName"]]))

      else:
        
          while True:
            await asyncio.sleep(self.config["ServerFrequencyInSeconds"])
            for node in self.nodes:
              temp_dict = self.nodes_dict[node["Name"]]
              temp_dict_counter = self.nodes_dict_counter[node["Name"]]
              
              for variable in node["Variables"]:
                count = temp_dict_counter[variable["TelemetryName"]]
                sequence_count = temp_dict[variable["TelemetryName"]]

                if count > (sequence_count - 1):
                  count = 0              

                # Choose the next value in the telemetry sequence for the variable
                self.nodes_dict_counter[node["Name"]][variable["TelemetryName"]] = (count + 1)
                value = variable["RangeValues"][count]
                log_msg = "[LOOP] {nn} {tn} {vw} {tc} SEQ({sc}) CUR({cc})"
                self.logger.info(log_msg.format(nn = node["Name"], tn = variable["TelemetryName"], vw = value, tc = count, sc = temp_dict[variable["TelemetryName"]], cc = temp_dict_counter[variable["TelemetryName"]]))


      return
class OpcUaServer():
    def __init__(self, Log, WhatIf):
        self.logger = Log
        self.whatif = WhatIf
        self.opcua_server_instance = None

        # Namespaces
        self.opcua_id_namespace_twins = None
        self.opcua_id_namespace_gateways = None
        self.opcua_id_namespace_devices = None

        # Load configuration
        self.config = []
        self.load_config()

        # Load Device Mapping
        self.devicescache = []
        self.load_devicescache()

        self.node_instances = {}
        self.variable_instances = {}

        # Telemetry Mapping
        self.map_telemetry = []
        self.map_telemetry_devices = []
        self.map_telemetry_interfaces = []
        self.map_telemetry_interfaces_variables = []

        # meta
        self.application_uri = None
        self.namespace = None
        self.device_capability_model_id = None
        self.device_capability_model = []
        self.device_name_prefix = None
        self.ignore_interface_ids = []

    # -------------------------------------------------------------------------------
    #   Function:   run
    #   Usage:      The start function starts the OPC Server
    # -------------------------------------------------------------------------------
    async def run(self):

        # OPCUA Server Run
        try:

            async with self.opcua_server_instance:
                while True:
                    await asyncio.sleep(self.config["ServerFrequencyInSeconds"]
                                        )
                    self.logger.info("[SERVER LOOP] STARTING:")

                    for device in self.map_telemetry["Devices"]:
                        for interface in device["Interfaces"]:
                            for variable in interface["Variables"]:

                                # Get the values from our ranges we are writing
                                value = variable["RangeValues"][
                                    int(variable["RangeValueCurrent"]) - 1]
                                self.logger.info("[SERVER LOOP] VALUE: %s" %
                                                 value)

                                # Update our iterator and boundaries
                                if int(variable["RangeValueCurrent"]) < int(
                                        variable["RangeValueCount"]):
                                    variable["RangeValueCurrent"] = int(
                                        variable["RangeValueCurrent"]) + 1
                                else:
                                    variable["RangeValueCurrent"] = 1

                                print("int(variable[RangeValueCurrent]) %s" %
                                      int(variable["RangeValueCurrent"]))
                                print("int(variable[RangeValueCount]) %s" %
                                      int(variable["RangeValueCount"]))

                                variable_node_instance = self.opcua_server_instance.get_node(
                                    variable["NodeId"])
                                await variable_node_instance.write_value(value)

            return
        except Exception as ex:
            self.logger.error("[ERROR] %s" % ex)
            self.logger.error(
                "[TERMINATING] We encountered an error in OpcUaServer::run()")

    # -------------------------------------------------------------------------------
    #   Function:   stop
    #   Usage:      The start function starts the OPC Server
    # -------------------------------------------------------------------------------
    async def stop(self):
        await self.opcua_server_instance.stop()
        return

    # -------------------------------------------------------------------------------
    #   Function:   setup
    #   Usage:      The setup function preps the configuration for the OPC Server
    # -------------------------------------------------------------------------------
    async def setup(self):

        # OPCUA Server Setup
        try:

            # configure the endpoint
            opc_url = self.config["ServerUrlPattern"].format(
                ip=self.config["IPAddress"], port=self.config["Port"])

            # init the server
            self.opcua_server_instance = Server()
            await self.opcua_server_instance.init()

            self.opcua_server_instance.set_endpoint(opc_url)
            self.opcua_server_instance.set_server_name(
                self.config["ServerDiscoveryName"])
            await self.opcua_server_instance.set_application_uri(
                self.config["ApplicationUri"])

            self.logger.info("[SERVER CONFIG] ENDPOINT: %s" % opc_url)
            self.logger.info("[SERVER CONFIG] APPLICATION URI: %s" %
                             self.config["ApplicationUri"])
            self.logger.info("[SERVER CONFIG] APPLICATION NAME: %s" %
                             self.config["ServerDiscoveryName"])

            # Set NameSpace(s)
            for pattern in self.config["IoTCentralPatterns"]:
                if pattern["ModelType"] == "Twins":
                    self.opcua_id_namespace_twins = await self.opcua_server_instance.register_namespace(
                        pattern["NameSpace"])
                if pattern["ModelType"] == "Gateways":
                    self.opcua_id_namespace_gateways = await self.opcua_server_instance.register_namespace(
                        pattern["NameSpace"])
                if pattern["ModelType"] == "Devices":
                    self.opcua_id_namespace_devices = await self.opcua_server_instance.register_namespace(
                        pattern["NameSpace"])

            self.logger.info("[SERVER CONFIG] NAMESPACE TWINS: %s" %
                             self.opcua_id_namespace_twins)
            self.logger.info("[SERVER CONFIG] NAMESPACE TWINS: %s" %
                             self.opcua_id_namespace_gateways)
            self.logger.info("[SERVER CONFIG] NAMESPACE DEVICES: %s" %
                             self.opcua_id_namespace_devices)

        except Exception as ex:
            self.logger.error("[ERROR] %s" % ex)
            self.logger.error(
                "[TERMINATING] We encountered an error in OPCUA Server Setup::setup()"
            )

        return

    # -------------------------------------------------------------------------------
    #   Function:   load_nodes_from_devicecache
    #   Usage:      The load_nodes_from_devicecache function enumerates the
    #               devicescache.json and creates a node for each kind of
    #               Iot Central Device. It looks at a Twin and registers all
    #               of the interfaces and for devices, registers the interface
    # -------------------------------------------------------------------------------
    async def load_nodes_from_devicecache(self):

        # OPCUA Server Setup
        try:

            # Setup root for map telemetry configuration file
            self.logger.info("[SERVER] INITIATED MAP TELEMETRY FILE: %s" %
                             self.map_telemetry)
            self.map_telemetry = self.create_map_telemetry_root(
                self.config["NameSpace"])

            # Data Type Mappings (OPCUA Datatypes to IoT Central Datatypes)
            variant_type = VariantType(self.logger)

            device_count = 0
            for device in self.devicescache["Devices"]:

                self.logger.info("[SERVER] DEVICE TYPE: %s" %
                                 device["DeviceType"])
                self.logger.info("[SERVER] DEVICE NAME: %s" % device["Name"])

                # DEVICE PER NODE
                namespace_id = None

                if device["DeviceType"] == "Twins":
                    namespace_id = self.opcua_id_namespace_twins
                elif device["DeviceType"] == "Gateways":
                    namespace_id = self.opcua_id_namespace_devices
                elif device["DeviceType"] == "Devices":
                    namespace_id = self.opcua_id_namespace_devices

                self.logger.info("[SERVER] DEVICE TYPE: %s" %
                                 device["DeviceType"])
                self.logger.info("[SERVER] DEVICE NAME: %s" % device["Name"])

                self.node_instances[device[
                    "Name"]] = await self.opcua_server_instance.nodes.objects.add_object(
                        namespace_id, device["Name"])
                self.logger.info("[SERVER] NODE ID: %s" %
                                 self.node_instances[device["Name"]])

                # Add the device info to the map telemetry file
                self.map_telemetry_devices.append(
                    self.create_map_telemetry_device(
                        device["Name"],
                        str(self.node_instances[device["Name"]]),
                        device["DeviceType"],
                        device["DeviceCapabilityModelId"]))
                self.logger.info(
                    "[SERVER] ADDED DEVICE TO MAP TELEMETRY FILE: %s" %
                    self.map_telemetry_devices)

                interface_count = 0
                for interface in device["Interfaces"]:

                    # Add the interface info to the map telemetry file
                    self.map_telemetry_interfaces.append(
                        self.create_map_telemetry_interface(
                            interface["Name"], interface["InterfacelId"],
                            interface["InterfaceInstanceName"]))
                    self.logger.info(
                        "[SERVER] ADDED INTERFACE TO MAP TELEMETRY FILE: %s" %
                        self.map_telemetry_interfaces)

                    config_interface = [
                        obj for obj in self.config["Nodes"]
                        if obj["InterfaceInstanceName"] ==
                        interface["InterfaceInstanceName"]
                    ]

                    for variable in config_interface[0]["Variables"]:
                        variable_name = variable["DisplayName"]
                        telemetry_name = variable["TelemetryName"]
                        range_value = variable["RangeValues"][0]
                        opc_variant_type = variant_type.map_variant_type(
                            variable["IoTCDataType"])

                        # Log Verbose Feedback
                        log_msg = "[SERVER] SETUP VARIABLES: *DISPLAY NAME: {dn} TELEMETRY NAME: {tn} *RANGE VALUE: {rv} *IoTC TYPE: {it} *OPC VARIANT TYPE {ovt} *OPC DATA TYPE {odt}"
                        self.logger.info(
                            log_msg.format(dn=variable["DisplayName"],
                                           vn=variable["TelemetryName"],
                                           tn=variable["TelemetryName"],
                                           rv=variable["RangeValues"][0],
                                           it=variable["IoTCDataType"],
                                           ovt=opc_variant_type,
                                           odt=opc_variant_type))

                        # Create Node Variable
                        nodeObject = await self.node_instances[
                            device["Name"]
                        ].add_variable(namespace_id, telemetry_name,
                                       range_value)
                        await nodeObject.set_writable()
                        self.variable_instances[telemetry_name] = nodeObject

                        # Append the variables to the Interfaces collection for the map telemetry file
                        self.map_telemetry_interfaces_variables.append(
                            self.create_map_telemetry_variable(
                                variable_name,
                                str(self.variable_instances[telemetry_name]),
                                telemetry_name, variable["IoTCDataType"],
                                variable["Frequency"],
                                variable["OnlyOnValueChange"],
                                variable["RangeValues"]))
                        self.logger.info(
                            "[SERVER] MAP TELEMETRY VARIABLES APPEND: %s" %
                            self.map_telemetry_interfaces[interface_count])

                    # Save the variables to the Map Telemetry [Interface] Collection
                    self.map_telemetry_interfaces[interface_count][
                        "Variables"] = self.map_telemetry_interfaces_variables
                    self.logger.info(
                        "[SERVER] MAP TELEMETRY INTERFACES APPEND: %s" %
                        self.map_telemetry_interfaces[interface_count])
                    interface_count = interface_count + 1
                    self.map_telemetry_interfaces_variables = []

                # Append the Interfaces to the Devices collection for the map telemetry file
                self.map_telemetry_devices[device_count][
                    "Interfaces"] = self.map_telemetry_interfaces
                device_count = device_count + 1
                self.map_telemetry_interfaces = []

            # Append the Devices to the Root collection for the map telemetry file
            self.map_telemetry["Devices"] = self.map_telemetry_devices
            self.logger.info("[SERVER] MAP TELEMETRY: %s" % self.map_telemetry)
            self.update_map_telemetry()

        except Exception as ex:
            self.logger.error("[ERROR] %s" % ex)
            self.logger.error(
                "[TERMINATING] We encountered an error in OPCUA Server Setup::load_nodes_from_devicecache()"
            )

        return

    # -------------------------------------------------------------------------------
    #   Function:   load_config
    #   Usage:      Loads the configuration from file
    # -------------------------------------------------------------------------------
    def load_config(self):

        config = Config(self.logger)
        self.config = config.data
        return

    # -------------------------------------------------------------------------------
    #   Function:   load_devicescache
    #   Usage:      Loads the Devices that have been registered and provisioned.
    #               This file is generated from the as-is state of the system
    #               when the OpcUaServer is started.
    # -------------------------------------------------------------------------------
    def load_devicescache(self):

        devicescache = DevicesCache(self.logger)
        self.devicescache = devicescache.data
        return

    # -------------------------------------------------------------------------------
    #   Function:   create_map_telemetry_root
    #   Usage:      Sets the root for the Map Telemetry configuration file
    # -------------------------------------------------------------------------------
    def create_map_telemetry_root(self, NameSpace):
        mapTelemetry = {
            "NameSpace": NameSpace,
            "Created": str(datetime.datetime.now()),
            "Devices": []
        }
        return mapTelemetry

    # -------------------------------------------------------------------------------
    #   Function:   create_map_telemetry_device
    #   Usage:      Adds a device to the map telemetry configuration file
    # -------------------------------------------------------------------------------
    def create_map_telemetry_device(self, Name, OpcUaNodeId, DeviceType,
                                    DeviceCapabilityModelId):
        mapTelemetry = {
            "Name": Name,
            "Connected": False,
            "ConnectedDateTime": "",
            "NodeId": OpcUaNodeId,
            "DeviceType": DeviceType,
            "DeviceCapabilityModelId": DeviceCapabilityModelId,
            "Interfaces": []
        }
        return mapTelemetry

    # -------------------------------------------------------------------------------
    #   Function:   create_map_telemetry_interface
    #   Usage:      Sets the node for the Map Telemetry configuration file
    # -------------------------------------------------------------------------------
    def create_map_telemetry_interface(self, Name, InterfacelId,
                                       InterfaceInstanceName):
        mapTelemetry = {
            "Name": Name,
            "InterfacelId": InterfacelId,
            "InterfaceInstanceName": InterfaceInstanceName,
            "Variables": []
        }
        return mapTelemetry

    # -------------------------------------------------------------------------------
    #   Function:   create_map_telemetry_variable
    #   Usage:      Sets the variable for the Map Telemetry configuration file
    # -------------------------------------------------------------------------------
    def create_map_telemetry_variable(self, DisplayName, OpcUaNodeId,
                                      TelemetryName, IoTCDataType, Frequency,
                                      OnlyOnValueChange, RangeValues):
        mapTelemetry = {
            "DisplayName": DisplayName,
            "NodeId": OpcUaNodeId,
            "TelemetryName": TelemetryName,
            "IoTCDataType": IoTCDataType,
            "Frequency": Frequency,
            "OnlyOnValueChange": OnlyOnValueChange,
            "RangeValueCount": len(RangeValues),
            "RangeValueCurrent": 1,
            "RangeValues": RangeValues
        }
        return mapTelemetry

    # -------------------------------------------------------------------------------
    #   Function:   update_map_telemetry
    #   Usage:      Saves the generated Map Telemetry File
    # -------------------------------------------------------------------------------
    def update_map_telemetry(self):
        map_telemetry_file = MapTelemetry(self.logger)
        map_telemetry_file.update_file(self.map_telemetry)
        return
Example #16
0
async def main():
    server = Server()
    await server.init()
    server.set_endpoint('opc.tcp://0.0.0.0:4840/UA/SampleServer')
    server.set_server_name('Custom structure demo server')

    # idx name will be used later for creating the xml used in data type dictionary
    url = 'http://examples.freeopcua.github.io'
    idx = await server.register_namespace(url)

    dict_builder = DataTypeDictionaryBuilder(server, idx, url, 'MyDictionary')
    await dict_builder.init()

    # add one basic structure
    basic_struct_name = 'BasicStructure'
    basic_struct = await dict_builder.create_data_type(basic_struct_name)
    basic_struct.add_field('ID', ua.VariantType.Int32)
    basic_struct.add_field('Gender', ua.VariantType.Boolean)
    basic_struct.add_field('Comments', ua.VariantType.String)

    # add an advance structure which uses our basic structure
    nested_struct_name = 'NestedStructure'
    nested_struct = await dict_builder.create_data_type(nested_struct_name)
    nested_struct.add_field('Name', ua.VariantType.String)
    nested_struct.add_field('Surname', ua.VariantType.String)
    # add a list of simple structure as field
    nested_struct.add_field('StuffArray', basic_struct, is_array=True)

    # this operation will write the OPC dict string to our new data type dictionary
    # namely the 'MyDictionary'

    await dict_builder.set_dict_byte_string()

    # get the working classes
    await server.load_type_definitions()

    # Create one test structure in our address space
    basic_var = await server.nodes.objects.add_variable(
        idx,
        'BasicStruct',
        None,
        datatype=basic_struct.data_type,
    )

    await basic_var.set_writable()
    var = ua.BasicStructure()
    var.ID = 3
    var.Gender = True
    var.Comments = 'Test string'
    await basic_var.write_value(var)

    # Create one advance test structure
    nested_var = await server.nodes.objects.add_variable(
        idx,
        'NestedStruct',
        None,
        datatype=nested_struct.data_type,
    )

    await nested_var.set_writable()
    var2 = ua.NestedStructure()
    var2.StuffArray = [var, var]
    var2.Name = 'Max'
    var2.Surname = 'Karl'
    await nested_var.write_value(var2)

    async with server:
        # see the xml value in our customized dictionary 'MyDictionary', only for debugging use
        print(getattr(dict_builder, '_type_dictionary').get_dict_value())

        # values can be write back and retrieved with the codes below.
        v1 = await basic_var.read_value()
        v2 = await nested_var.read_value()

        #embed()
        while True:
            await asyncio.sleep(1)
Example #17
0
async def _uaserver():
    parser = argparse.ArgumentParser(
        description=
        "Run an example OPC-UA server. By importing xml definition and using uawrite command line, it is even possible to expose real data using this server"
    )
    # we setup a server, this is a bit different from other tool so we do not reuse common arguments
    parser.add_argument(
        "-u",
        "--url",
        help="URL of OPC UA server, default is opc.tcp://0.0.0.0:4840",
        default='opc.tcp://0.0.0.0:4840',
        metavar="URL")
    parser.add_argument(
        "-v",
        "--verbose",
        dest="loglevel",
        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
        default='WARNING',
        help="Set log level")
    parser.add_argument(
        "-x",
        "--xml",
        metavar="XML_FILE",
        help="Populate address space with nodes defined in XML")
    parser.add_argument("-p",
                        "--populate",
                        action="store_true",
                        help="Populate address space with some sample nodes")
    parser.add_argument(
        "-c",
        "--disable-clock",
        action="store_true",
        help=
        "Disable clock, to avoid seeing many write if debugging an application"
    )
    parser.add_argument(
        "-s",
        "--shell",
        action="store_true",
        help="Start python shell instead of randomly changing node values")
    parser.add_argument("--certificate", help="set server certificate")
    parser.add_argument("--private_key", help="set server private key")
    args = parser.parse_args()
    logging.basicConfig(format="%(levelname)s: %(message)s",
                        level=getattr(logging, args.loglevel))

    server = Server()
    server.set_endpoint(args.url)
    if args.certificate:
        server.load_certificate(args.certificate)
    if args.private_key:
        server.load_private_key(args.private_key)
    server.disable_clock(args.disable_clock)
    server.set_server_name("FreeOpcUa Example Server")
    if args.xml:
        server.import_xml(args.xml)
    if args.populate:

        @uamethod
        def multiply(parent, x, y):
            print("multiply method call with parameters: ", x, y)
            return x * y

        uri = "http://examples.freeopcua.github.io"
        idx = server.register_namespace(uri)
        objects = server.nodes.objects
        myobj = objects.add_object(idx, "MyObject")
        mywritablevar = myobj.add_variable(idx, "MyWritableVariable", 6.7)
        mywritablevar.set_writable(
        )  # Set MyVariable to be writable by clients
        myvar = myobj.add_variable(idx, "MyVariable", 6.7)
        myarrayvar = myobj.add_variable(idx, "MyVarArray", [6.7, 7.9])
        myprop = myobj.add_property(idx, "MyProperty", "I am a property")
        mymethod = myobj.add_method(
            idx, "MyMethod", multiply,
            [ua.VariantType.Double, ua.VariantType.Int64],
            [ua.VariantType.Double])

    try:
        await server.init()
        async with server:

            if args.shell:
                embed()
            elif args.populate:
                count = 0
                while True:
                    await asyncio.sleep(1)
                    myvar.write_value(math.sin(count / 10))
                    myarrayvar.write_value(
                        [math.sin(count / 10),
                         math.sin(count / 100)])
                    count += 1
            else:
                while True:
                    await asyncio.sleep(1)
    except OSError as e:
        print(e)
        sys.exit(1)
    except KeyboardInterrupt:
        pass
    sys.exit(0)
Example #18
0
async def main():
    # setup our server
    server = Server()
    await server.init()
    server.set_endpoint('opc.tcp://0.0.0.0:4840')
    # server.set_endpoint('opc.tcp://192.168.100.170:4840')
    # setup our own namespace, not really necessary but should as spec
    server.set_server_name("SU OPC UA Server read test")
    # server.set_security_policy([
    #     ua.SecurityPolicyType.NoSecurity,
    #     ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
    #     ua.SecurityPolicyType.Basic256Sha256_Sign])

    uri = 'http://examples.freeopcua.github.io'
    idx = await server.register_namespace(uri)

    await server.import_xml('kuka2.xml')
    ## get Objects node, this is where we should put our nodes
    # await server.start()

    # root = server.get_root_node()
    # # _logger.info("Root node is: %r", root)
    # objects = server.get_objects_node()
    # # _logger.info("Objects node is: %r", objects)
    # # print(server.get_namespace_index())
    # # myvar = await root.get_child(["0:Objects","3:KUKA_1",'0:x'])
    # # bo=await objects.get_children()
    # myvar = await objects.get_children()
    # # myvar.
    # # myvar(['0:actuator1'])
    # print(myvar)

    # root = server.get_root_node()
    # actuator1 = await root.get_child(["0:Objects", "0:Actuator", '0:actuator1'])
    # actuator2 = await root.get_child(["0:Objects", "0:Actuator", '0:actuator2'])
    # actuator3 = await root.get_child(["0:Objects", "0:Actuator", '0:actuator3'])
    # actuator4 = await root.get_child(["0:Objects", "0:Actuator", '0:actuator4'])
    # degree1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree1'])
    # degree2 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree2'])
    # degree3 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree3'])
    # degree4 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree4'])
    # degree5 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree5'])
    # degree6 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Degree', '0:degree6'])
    # degree7 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree7'])
    # degree8 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree8'])
    # degree9 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree9'])
    # degree10 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree10'])
    # degree11 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree11'])
    # degree12 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Degree_R', '0:degree12'])
    # x1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:x1'])
    # x2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:x2'])
    # y1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:y1'])
    # y2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:y2'])
    # z1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:z1'])
    # z2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:z2'])
    # a1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:a1'])
    # a2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:a2'])
    # b1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:b1'])
    # b2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:b2'])
    # c1 = await root.get_child(["0:Objects", "0:Drulling_Robot", '0:Joint', '0:c1'])
    # c2 = await root.get_child(["0:Objects", "0:Riveting_Robot", '0:Joint_R', '0:c2'])
    # normal1 = await root.get_child(["0:Objects", "0:Normals",'0:normal1'])
    # normal2 = await root.get_child(["0:Objects", "0:Normals",'0:normal2'])
    # normal3 = await root.get_child(["0:Objects", "0:Normals",'0:normal3'])

    # data=[actuator1,actuator2,actuator3,actuator4,degree1,degree2,degree3,degree4,
    #       degree5,degree6,degree7,degree8,degree9,degree10,degree11,degree12,x1,x2,
    #       y1,y2,z1,z2,a1,a2,b1,b2,c1,c2,normal1,normal2,normal3]

    # print(f'{bo}')
    # aa=await server.get_objects_node().get_child(
    #     ["0:Objects", "0:Server"]).nodeid
    # print(aa)
    # myobject2_type_nodeid = server.get_root_node().get_child(
    #     ["0:Types", "0:ObjectTypes", "0:BaseObjectType", "%d:StateType" % idx]).nodeid
    # myobject3_type_nodeid = server.get_node(ua.ObjectIds.BaseObjectType).get_child(
    #     ["%d:MyCustomObjectType" % idx]).nodeid
    #
    # # Node objects have methods to read and write node attributes as well as browse or populate address space
    # print("Children of root are: %r", await objects.get_children())

    # objects = server.get_objects_node()
    # aa = objects.get_child([f"{idx}:sss"])
    # aa.write_value(True)
    # print(aa)

    # todo 对于变量固定的 适合用xml生成信息模型
    # kukaobj1=await objects.add_object(idx,'KUKA_ROBOT_1')
    # kukafloder1=await kukaobj1.add_folder(idx,'Axis')
    # kukavar1 = kukafloder1.add_variable()
    # kukavar2 = kukafloder1.add_variable()
    # kukavar3 = kukafloder1.add_variable()
    # kukavar4 = kukafloder1.add_variable()
    # kukavar5 = kukafloder1.add_variable()
    # kukavar6 = kukafloder1.add_variable()
    # kukafloder2 = await kukaobj1.add_folder(idx, 'Degree')
    # kukavar7 = kukafloder2.add_variable()
    # kukavar8 = kukafloder1.add_variable()
    # kukavar9 = kukafloder1.add_variable()
    # kukavar10 = kukafloder1.add_variable()
    # kukavar11 = kukafloder1.add_variable()
    # kukavar12 = kukafloder1.add_variable()

    # myobj = await objects.add_object(idx, 'MyObject')

    # # Set MyVariable to be writable by clients
    # await myvar.set_writable()
    # await objects.add_method(
    #     ua.NodeId('ServerMethod', 2), ua.QualifiedName('ServerMethod', 2),
    #     func, [ua.VariantType.Int64], [ua.VariantType.Int64]
    # )
    _logger.info('Starting server!')
    async with server:
        count = 0

        while True:
            await asyncio.sleep(1)
            count += 0.1
Example #19
0
class DataServer:
    """
    OPC-UA Asynchronous Data Server

    NOTE: attributes that are specified in the format
          'Node, data_type' mean that the attribute is an OPC-UA
          node that holds the specified data type

    Attributes:
    ----------
    __server_url: str
        IP and Port to which the OPC-UA server will send data to.
        Format:  opc.tcp://[IP]:[PORT]
    __address_space_name: str
        OPC-UA server data address space name
    __server_name: str
        name of the OPC-UA server
    __server: Server
        asynchronous OPC-UA server

    __address_space: Node
        OPC-UA server address space
    __sensor: Node
        main objects that holds all variables shared by the server

    __voltage_ramp: Node, list
        list of voltages to apply to plasma sensor
    __voltage_sweep_time: Node, float
        wait time between measurements (in .1 seconds)
    __current_filter: Node, str
        Data filter to apply to final list of current
                               Values: 'None' -> No filter applied
                                       'SOS' -> SOS filter
    __sensor_to_use: Node, str
        Plasma sensor to use for measurements
                                Values: 'SLP', 'DLP', 'HEA'
                                SLP -> Single Langmuir Probe
                                DLP -> Double Langmuir Probe
                                HEA -> Hyperbolic Energy Analyzer

    __abort_measurements: Node, bool
        Signals the server to abort a measurement
    __is_client_data_fully_sent: Node, bool
        Client signal that it has finished sending measurement parameters
    __is_measurements_running: Node, bool
        Specifies if the server is running a measurement
    __is_measurements_finished: Node, bool
        Server signal that specifies that it has finished calculating measurements

    __current_measurements: Node, str
        Holds the calculated 'current' from the plasma sensor
    __time_measurements: Node, str
        Times in which the plasma sensor's current was calculated

    Methods:
    _______
    __initialize_server():
         Initializes the server and all nodes handled by the server
    __flush_measurement_parameters():
         Flushes the values of a measurement so conflicts can be avoided when doing new measurements
    __check_client_data_received():
        Checks if client data has been fully received

    __run_measurements():
         Runs measurements with entered measurement parameters
    __run_SLP_measurements():
        Runs measurements for a Single Langmuir Probe (SLP) plasma sensor
    __run_DLP_measurements():
        Runs measurements for a Double Langmuir Probe (DLP) plasma sensor
    __run_HEA_measurements():
        Runs measurements for a Hyperbolic Energy Analyzer (HEA) plasma sensor

    start_server():
        Awaits for a client connection and serves server data indefinitely
        and asynchronously to server url.
    start_server_task():
        Starts server synchronously (without using asyncio)
    close_server():
        Stops server from serving data
    stop_measurements():
        Signals the server to abort generating measurements

    set_server_url(server_url: str):
        Change server url to serve data on
    get_server_url():
        Returns server url to serve data on
    get_server_name():
        Returns server name

    Shares the following data with clients:
    --------------------------------------
    class Sensor:
        voltage_ramp: list, writeable
            List specifying all voltages to read from a plasma sensor.
            Format: [2, 2.5, 3] -> all values are voltages

        voltage_sweep_time: int, writeable
            Wait time between measurements (in seconds)

        current_filter: str, writeable
            Data filter to apply to final list of current
            Values: 'None' -> No filter applied
                    'SOS' -> SOS filter

        sensor_to_use: str, writeable
            Plasma sensor to use for measurement
            Values: 'SLP', 'DLP', 'HEA'
            SLP -> Single Langmuir Probe
            DLP -> Double Langmuir Probe
            HEA -> Hyperbolic Energy Analyzer

        abort_measurements: bool, writeable
            if set to true, aborts running measurements

        is_client_data_fully_sent: bool, writeable
            if set to true, client data has been fully received and measurement can be run

        is_measurements_running: bool, not writeable
            if set to true, server is currently running measurements

        is_measurements_finished: bool, not writeable
            if set to true, server is done calculating measurements

        NOTE: the current measurements and time measurements holders are currently implemented as string
        data structures. this should be changed to use lists as it is more appropriate

        current_measurements: str, not writeable
            returns the values for all current measurements divided by commas ','

        time_measurements: str, not writeable
            returns the values for all times in which measurements where taken divided by commas ','
    """

    __server_url = ""
    __address_space_name = "OPCUA_PLASMA_MEASUREMENTS_SERVER"
    __server_name = "Plasma Meter Server"
    __server = None

    __address_space = None
    __sensor = None

    __voltage_ramp = None
    __voltage_sweep_time = None
    __current_filter = None
    __sensor_to_use = None

    __abort_measurements = None
    __is_client_data_fully_sent = None
    __is_measurements_running = None
    __is_measurements_finished = None

    __current_measurements = None
    __time_measurements = None

    def __init__(self, server_url: str = "opc.tcp://127.0.0.1:9002"):
        """
        Initialize with server url
        Default url is set to local loopback address
        :param server_url: IP and Port to which the OPC-UA server will send data to.
                           Format:  opc.tcp://[IP]:[PORT]
        """
        self.set_server_url(server_url)

    async def __initialize_server(self):
        """
        Initializes the server and all nodes handled by the server
        :return: None
        """
        # instantiates server
        self.__server = Server()
        await self.__server.init()
        self.__server.set_endpoint(self.get_server_url())
        self.__server.set_server_name(self.get_server_name())

        # sets server address space
        self.__address_space = await self.__server.register_namespace(self.__address_space_name)

        # sensor object
        self.__sensor = await self.__server.nodes.objects.add_object(self.__address_space, 'sensor')

        #  self.__sensor object variables (see method docstring for description of each)
        self.__voltage_ramp = await self.__sensor.add_variable(self.__address_space, "voltage_ramp", val='')
        self.__voltage_sweep_time = await self.__sensor.add_variable(self.__address_space, "voltage_sweep_time", 0.0)
        self.__current_filter = await self.__sensor.add_variable(self.__address_space, "current_filter", val='None')
        self.__sensor_to_use = await self.__sensor.add_variable(self.__address_space, "sensor_to_use", '')
        self.__abort_measurements = await self.__sensor.add_variable(self.__address_space, "stop_measurements", False)
        self.__is_client_data_fully_sent = await self.__sensor.add_variable(self.__address_space,
                                                                            "is_client_data_fully_sent", val=False)
        self. __is_measurements_running = await self.__sensor.add_variable(self.__address_space,
                                                                           "is_measurements_running", val=False)
        self.__is_measurements_finished = await self.__sensor.add_variable(self.__address_space,
                                                                           "is_measurements_finished", val=False)
        self.__current_measurements = await self.__sensor.add_variable(self.__address_space,
                                                                       "current_measurements", val='')
        self.__time_measurements = await self.__sensor.add_variable(self.__address_space,
                                                                    "time_measurements", val='')

        # makes the sensor object's variables that the client can modify writeable
        await self.__voltage_ramp.set_writable()
        await self.__voltage_sweep_time.set_writable()
        await self.__sensor_to_use.set_writable()
        await self.__abort_measurements.set_writable()
        await self.__is_client_data_fully_sent.set_writable()
        await self.__current_filter.set_writable()

    async def __flush_measurement_parameters(self):
        """
        Flushes the values of a measurement so conflicts can be avoided when doing new measurements
        :return: None
        """
        # flushes measurement parameters
        await self.__voltage_ramp.set_value('')
        await self.__voltage_sweep_time.set_value(0.0)
        await self.__sensor_to_use.set_value('')
        await self.__is_client_data_fully_sent.set_value(False)
        await self.__is_measurements_finished.set_value(False)
        await self.__abort_measurements.set_value(False)

    async def __check_client_data_received(self):
        """
        Checks if client data has been fully received
        :return:  True if client data has been fully received, false if not
        :rtype: bool
        """
        if await self.__is_client_data_fully_sent.get_value():
            return True
        else:
            return False

    async def __run_measurements(self):
        """
        Runs measurements with entered measurement parameters
        :return: None
        """

        await self.__is_measurements_running.set_value(True)

        # runs measurements for the selected plasma sensor
        if (await self.__sensor_to_use.get_value()) == 'SLP':
            await self.__run_SLP_measurements()

        elif (await self.__sensor_to_use.get_value()) == 'DLP':
            await self.__run_DLP_measurements()

        elif (await self.__sensor_to_use.get_value()) == 'HEA':
            await self.__run_HEA_measurements()

        else:
            print('SERVER ERROR: selected sensor not implemented')

        await self.__is_measurements_running.set_value(False)

    async def __run_SLP_measurements(self):
        """
        Runs measurements for a Single Langmuir Probe (SLP) plasma sensor
        :return: None
        """

        # variables to generate measurements
        measurement_voltage_sweep_time = await self.__voltage_sweep_time.get_value()
        measurement_voltage_ramp = await self.__voltage_ramp.get_value()
        number_of_measurements = float(len(measurement_voltage_ramp))
        step_time = float(measurement_voltage_sweep_time) / number_of_measurements
        current_filter = await self.__current_filter.get_value()

        # current sensing resistor of the Single Langmuir Probe
        shunt_resistor = 200.0

        # holds the generated current and time values
        calculated_current_measurements = ''
        calculated_time_measurements = ''

        voltages = [float(v) for v in (await self.__voltage_ramp.get_value()).split(',')]

        # runs measurements with no current filter
        if current_filter == 'None':

            # does measurements for each voltage
            for voltage in voltages:

                # stop measurements if abort flag is raised
                if await self.__abort_measurements.get_value():
                    break

                # NOTE: voltage must be sent to sensor before retrieving the current\
                # NOTE: time.sleep was used instead of asyncio.sleep to preserve miliseconds needed for runtime
                await asyncio.sleep(step_time)

                current = (voltage * -2.0) / shunt_resistor
                # print(time.time())

                # appends new current and time measurements
                # NOTE: join was used instead of string concatenation to preserve real time speed of application
                calculated_current_measurements = ''.join((calculated_current_measurements, str(current), ','))
                calculated_time_measurements = ''.join((calculated_time_measurements, str(datetime.datetime.now()), ','))

                # continuously updates current and time values
                await self.__current_measurements.set_value(calculated_current_measurements[:-1])
                await self.__time_measurements.set_value(calculated_time_measurements[:-1])

        # uses SOS filter for current
        elif current_filter == 'SOS':

            # does measurements for each voltage
            for voltage in voltages.split(','):

                # stop measurements if abort flag is raised
                if await self.__abort_measurements.get_value():
                    break

                # NOTE: voltage must be sent to sensor before retrieving the current
                await asyncio.sleep(step_time)

                current = (float(voltage) * 2.0) / shunt_resistor

                # appends new current and time measurements
                calculated_current_measurements += str(current) + ','
                calculated_time_measurements += str(datetime.datetime.now()) + ','

                # continuously updates current and time values
                await self.__current_measurements.set_value(calculated_current_measurements[:-1])
                await self.__time_measurements.set_value(calculated_time_measurements[:-1])

        else:
            print(f'SERVER ERROR: current filter not properly specified. If none is used, please select "None"')

        print(f'the current is {calculated_current_measurements}')
        print(f'the time is {calculated_time_measurements}')

        # transmits calculated data
        await self.__current_measurements.set_value(calculated_current_measurements[:-1])
        await self.__time_measurements.set_value(calculated_time_measurements[:-1])
        await self.__is_measurements_finished.set_value(True)

        print(f"SERVER RESULT TRANSMITTING: server transmitting data result on {self.get_server_url()}")
        await asyncio.sleep(10)

    async def __run_DLP_measurements(self):
        """
        Runs measurements for a Double Langmuir Probe (DLP) plasma sensor
        :return: None
        """
        pass

    async def __run_HEA_measurements(self):
        """
        Runs measurements for a Hyperbolic Energy Analyzer (HEA) plasma sensor
        :return: None
        """
        pass

    async def start_server(self):
        """
        Awaits for a client connection and serves server data indefinitely
        and asynchronously to server url.

        Requires to be called as an asyncio function

        Requires voltage_ramp, voltage_sweep_time, sensor_to_use, and client_data_fully_sent to be
        sent by client to run

        :return: None
        """
        await self.__initialize_server()

        # transmits that server is open to receive data
        print(f"SERVER STARTED: server open at {self.get_server_url()}")
        async with self.__server:

            # waits to receive server data
            while True:

                # print('SERVER STILL AWAITING')

                # client data received and measurements can start
                if await self.__check_client_data_received():

                    print(f"SERVER DATA RECEIVED: server received measurement data on {self.get_server_url()}")
                    await self.__run_measurements()

                    # flushes parameters after measurements have finished
                    await self.__flush_measurement_parameters()

                # delay for server to check for data changes
                await asyncio.sleep(2)

    def start_server_task(self):
        """
        Starts server synchronously (without using asyncio)
        :return: None
        """
        asyncio.run(self.start_server())

    async def close_server(self):
        """
        Stops server from serving data
        :return: None
        """
        print(f"CLOSE SERVER: closing server at {self.get_server_url()}")
        await self.__server.stop()

    async def stop_measurements(self):
        """
        Signals the server to abort generating measurements
        :return: None
        """
        # aborts measurements if measurements are running
        if await self.__is_measurements_running.get_value():
            await self.__abort_measurements.set_value(True)
        else:
            print("SERVER ERROR: measurements couldn't be stopped as no measurement is running")

    def set_server_url(self, server_url: str):
        """
        Change server url to serve data on
        :param server_url: IP and Port to which the OPC-UA server will send data to.
                           Format:  opc.tcp://[IP]:[PORT]
        :return: None
        """
        self.__server_url = server_url

    def get_server_url(self):
        """
        Returns server url to serve data on
        :return: IP and Port to which the OPC-UA server will send data to.
                 Format:  opc.tcp://[IP]:[PORT]
        :rtype: str
        """
        return self.__server_url

    def get_server_name(self):
        """
        Returns server name
        :return: string name of server
        :rtype: str
        """
        return self.__server_name
Example #20
0
async def main():
    # optional: setup logging
    #logger = logging.getLogger("asyncua.address_space")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.internal_server")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.binary_server_asyncio")
    # logger.setLevel(logging.DEBUG)
    #logger = logging.getLogger("asyncua.uaprocessor")
    # logger.setLevel(logging.DEBUG)

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

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

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

    # populating our address space

    # First a folder to organise our nodes
    myfolder = await server.nodes.objects.add_folder(idx, "myEmptyFolder")
    # instanciate one instance of our device
    mydevice = await server.nodes.objects.add_object(idx, "Device0001", dev)
    mydevice_var = await mydevice.get_child(
        [f"{idx}:controller",
         f"{idx}:state"])  # get proxy to our device state variable
    # create directly some objects and variables
    myobj = await server.nodes.objects.add_object(idx, "MyObject")
    myvar = await myobj.add_variable(idx, "MyVariable", 6.7)
    await myvar.set_writable()  # Set MyVariable to be writable by clients
    mystringvar = await myobj.add_variable(idx, "MyStringVariable",
                                           "Really nice string")
    await mystringvar.set_writable(
    )  # Set MyVariable to be writable by clients
    mydtvar = await myobj.add_variable(idx, "MyDateTimeVar", datetime.utcnow())
    await mydtvar.set_writable()  # Set MyVariable to be writable by clients
    myarrayvar = await myobj.add_variable(idx, "myarrayvar", [6.7, 7.9])
    myarrayvar = await myobj.add_variable(
        idx, "myStronglytTypedVariable", ua.Variant([], ua.VariantType.UInt32))
    myprop = await myobj.add_property(idx, "myproperty", "I am a property")
    mymethod = await myobj.add_method(idx, "mymethod", func,
                                      [ua.VariantType.Int64],
                                      [ua.VariantType.Boolean])
    multiply_node = await myobj.add_method(
        idx, "multiply", multiply,
        [ua.VariantType.Int64, ua.VariantType.Int64], [ua.VariantType.Int64])

    # import some nodes from xml
    await server.import_xml("custom_nodes.xml")

    # creating a default event object
    # The event object automatically will have members for all events properties
    # you probably want to create a custom event type, see other examples
    myevgen = await server.get_event_generator()
    myevgen.event.Severity = 300

    # starting!
    async with server:
        print("Available loggers are: ",
              logging.Logger.manager.loggerDict.keys())
        # enable following if you want to subscribe to nodes on server side
        #handler = SubHandler()
        #sub = server.create_subscription(500, handler)
        #handle = sub.subscribe_data_change(myvar)
        # trigger event, all subscribed clients wil receive it
        var = await myarrayvar.read_value(
        )  # return a ref to value in db server side! not a copy!
        var = copy.copy(
            var
        )  # WARNING: we need to copy before writting again otherwise no data change event will be generated
        var.append(9.3)
        await myarrayvar.write_value(var)
        await mydevice_var.write_value("Running")
        await myevgen.trigger(message="This is BaseEvent")
        await server.write_attribute_value(
            myvar.nodeid, ua.DataValue(0.9)
        )  # Server side write method which is a bit faster than using write_value
        while True:
            await asyncio.sleep(0.1)
            await server.write_attribute_value(myvar.nodeid,
                                               ua.DataValue(sin(time.time())))
Example #21
0
class server:
    def __init__(self):
        logging.info("Creating a opc server")
        self._server = Server()
        self._config = False
        self.nsindex = ""

    async def NewOPCServer(self, IP):
        # now setup our server
        await self._server.init()
        self._server.disable_clock()  #for debuging
        self.IP = IP.strip()

        self.mynodes = []
        self._server.set_endpoint(
            self.IP
        )  #ip removing whitespace Address to pass "opc.tcp://0.0.0.0:4840/freeopcua/server/"
        self._server.set_server_name("OPC Server Name")

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

    def checkdata(self, data):
        if len(data) < 5:
            return False
        if len(data['measure']) < 1:
            return False
        #TODO implement more data check

    async def LoadConfig(self, path):

        with open(path) as f:
            data = json.load(f)
        if not self.checkdata(data):
            return False
        # setup our own namespace
        await self._server.register_namespace(self.nsindex)
        self._config = False
        self.scan = data['scaninterval']
        self.nsindex = data['namespaceindex']
        self.namespace = data['namespace']
        self.devices = data['device']

        #   create a new node type we can instantiate in our address space
        dev = await self._server.nodes.base_object_type.add_object_type(
            int(self.nsindex), self.devices)

        #Creating the nodes

        i = 0
        for element in data['measure']:
            self.mynodes.append(await dev.add_variable(
                ua.NodeId.from_string('ns=' + self.nsindex + ';s=' +
                                      self.namespace + '.' + self.devices +
                                      '.' + element['name']), element['name'],
                0))
            await self.mynodes[i].set_writable()
            i += 1

        myevgen = await self._server.get_event_generator()
        myevgen.event.Severity = 300
        logging.info("Configuration loaded")
        self._config = True

    async def Start(self):
        if self._config:
            async with self._server:
                #print("Available loggers are: ", logging.Logger.manager.loggerDict.keys())
                logging.info("Server Started")
                while True:
                    await asyncio.sleep(self.scan)
                    for element in self.mynodes:
                        #updating values
                        await self._server.write_attribute_value(
                            element.nodeid, ua.DataValue(sin(time.time())))
        logging.warning("The server need to be configure it first")

    async def CreateXML(self):
        ipremove = self.IP.replace("opc.tcp://", "")
        port = ipremove[ipremove.index(":") + 1:]
        #creating the xml
        await self._server.export_xml_by_ns(
            "gen/Configuration" + port + ".xml", int(self.nsindex))
        logging.info("XML File created successfully")