Commit d5bacbc8 authored by Kolja Brix's avatar Kolja Brix Committed by oroulet

Fix some more typos.

parent 888462e1
...@@ -53,7 +53,7 @@ async with Client(url='opc.tcp://localhost:4840/freeopcua/server/') as client: ...@@ -53,7 +53,7 @@ async with Client(url='opc.tcp://localhost:4840/freeopcua/server/') as client:
value = await node.read_value() value = await node.read_value()
``` ```
Of course you can also call the `connect`, `disconnect` methods yourself if you do not want to use the context manager. Of course, you can also call the `connect`, `disconnect` methods yourself if you do not want to use the context manager.
See the example folder and the code for more information on the client API. See the example folder and the code for more information on the client API.
......
...@@ -123,8 +123,8 @@ class Client: ...@@ -123,8 +123,8 @@ class Client:
def set_locale(self, locale: List[str]) -> None: def set_locale(self, locale: List[str]) -> None:
""" """
Sets the prefred locales of the client, the server chooses which locale he can provide. Sets the preferred locales of the client, the server chooses which locale he can provide.
Normaly the first matching locale in the list will be chossen, by the server. Normally the first matching locale in the list will be chosen, by the server.
Call this before connect() Call this before connect()
""" """
self._locale = locale self._locale = locale
...@@ -390,7 +390,7 @@ class Client: ...@@ -390,7 +390,7 @@ class Client:
async def create_session(self): async def create_session(self):
""" """
send a CreateSessionRequest to server with reasonable parameters. send a CreateSessionRequest to server with reasonable parameters.
If you want o modify settings look at code of this methods If you want to modify settings look at code of these methods
and make your own and make your own
""" """
self._closing = False self._closing = False
...@@ -467,8 +467,8 @@ class Client: ...@@ -467,8 +467,8 @@ class Client:
async def _renew_channel_loop(self): async def _renew_channel_loop(self):
""" """
Renew the SecureChannel before the SecureChannelTimeout will happen. Renew the SecureChannel before the SecureChannelTimeout will happen.
In theory we could do that only if no session activity In theory, we could do that only if no session activity,
but it does not cost much.. but it does not cost much.
""" """
try: try:
# Part4 5.5.2.1: # Part4 5.5.2.1:
......
...@@ -47,7 +47,7 @@ class UASocketProtocol(asyncio.Protocol): ...@@ -47,7 +47,7 @@ class UASocketProtocol(asyncio.Protocol):
# needed to pass params from asynchronous request to synchronous data receive callback, as well as # needed to pass params from asynchronous request to synchronous data receive callback, as well as
# passing back the processed response to the request so that it can return it. # passing back the processed response to the request so that it can return it.
self._open_secure_channel_exchange: Union[ua.OpenSecureChannelResponse, ua.OpenSecureChannelParameters, None] = None self._open_secure_channel_exchange: Union[ua.OpenSecureChannelResponse, ua.OpenSecureChannelParameters, None] = None
# Hook for upperlayer tasks before a request is send (optional) # Hook for upper layer tasks before a request is sent (optional)
self.pre_request_hook: Optional[Callable[[], Awaitable[None]]] = None self.pre_request_hook: Optional[Callable[[], Awaitable[None]]] = None
def connection_made(self, transport: asyncio.Transport): # type: ignore def connection_made(self, transport: asyncio.Transport): # type: ignore
...@@ -153,8 +153,8 @@ class UASocketProtocol(asyncio.Protocol): ...@@ -153,8 +153,8 @@ class UASocketProtocol(asyncio.Protocol):
""" """
timeout = self.timeout if timeout is None else timeout timeout = self.timeout if timeout is None else timeout
if self.pre_request_hook: if self.pre_request_hook:
# This will propagade exceptions from background tasks to the libary user before calling a request which will # This will propagate exceptions from background tasks to the library user before calling a request which will
# timeout then. # time out then.
await self.pre_request_hook() await self.pre_request_hook()
try: try:
data = await asyncio.wait_for(self._send_request(request, timeout, message_type), timeout if timeout else None) data = await asyncio.wait_for(self._send_request(request, timeout, message_type), timeout if timeout else None)
...@@ -230,7 +230,7 @@ class UASocketProtocol(asyncio.Protocol): ...@@ -230,7 +230,7 @@ class UASocketProtocol(asyncio.Protocol):
async def close_secure_channel(self): async def close_secure_channel(self):
""" """
Close secure channel. Close secure channel.
It seems to trigger a shutdown of socket in most servers, so be prepare to reconnect. It seems to trigger a shutdown of socket in most servers, so be prepared to reconnect.
OPC UA specs Part 6, 7.1.4 say that Server does not send a CloseSecureChannel response OPC UA specs Part 6, 7.1.4 say that Server does not send a CloseSecureChannel response
and should just close socket. and should just close socket.
""" """
...@@ -310,7 +310,7 @@ class UaClient(AbstractSession): ...@@ -310,7 +310,7 @@ class UaClient(AbstractSession):
async def close_secure_channel(self): async def close_secure_channel(self):
""" """
close secure channel. It seems to trigger a shutdown of socket close secure channel. It seems to trigger a shutdown of socket
in most servers, so be prepare to reconnect in most servers, so be prepared to reconnect
""" """
if not self.protocol or self.protocol.state == UASocketProtocol.CLOSED: if not self.protocol or self.protocol.state == UASocketProtocol.CLOSED:
self.logger.warning("close_secure_channel was called but connection is closed") self.logger.warning("close_secure_channel was called but connection is closed")
...@@ -485,7 +485,7 @@ class UaClient(AbstractSession): ...@@ -485,7 +485,7 @@ class UaClient(AbstractSession):
response.Parameters.SubscriptionId response.Parameters.SubscriptionId
) )
if not self._publish_task or self._publish_task.done(): if not self._publish_task or self._publish_task.done():
# Start the publish loop if it is not yet running # Start the publishing loop if it is not yet running
# The current strategy is to have only one open publish request per UaClient. This might not be enough # The current strategy is to have only one open publish request per UaClient. This might not be enough
# in high latency networks or in case many subscriptions are created. A Set of Tasks of `_publish_loop` # in high latency networks or in case many subscriptions are created. A Set of Tasks of `_publish_loop`
# could be used if necessary. # could be used if necessary.
...@@ -494,7 +494,7 @@ class UaClient(AbstractSession): ...@@ -494,7 +494,7 @@ class UaClient(AbstractSession):
async def inform_subscriptions(self, status: ua.StatusCode): async def inform_subscriptions(self, status: ua.StatusCode):
""" """
Inform all current subscriptions with a status code. This calls the handlers status_change_notification Inform all current subscriptions with a status code. This calls the handler's status_change_notification
""" """
status_message = ua.StatusChangeNotification(Status=status) status_message = ua.StatusChangeNotification(Status=status)
notification_message = ua.NotificationMessage(NotificationData=[status_message]) notification_message = ua.NotificationMessage(NotificationData=[status_message])
...@@ -570,7 +570,7 @@ class UaClient(AbstractSession): ...@@ -570,7 +570,7 @@ class UaClient(AbstractSession):
continue continue
except BadNoSubscription: # See Spec. Part 5, 13.8.1 except BadNoSubscription: # See Spec. Part 5, 13.8.1
# BadNoSubscription is expected to be received after deleting the last subscription. # BadNoSubscription is expected to be received after deleting the last subscription.
# We use this as a signal to exit this task and stop sending PublishRequests. This is easier then # We use this as a signal to exit this task and stop sending PublishRequests. This is easier than
# checking if there are no more subscriptions registered in this client (). A Publish response # checking if there are no more subscriptions registered in this client (). A Publish response
# could still arrive before the DeleteSubscription response. # could still arrive before the DeleteSubscription response.
# #
...@@ -780,6 +780,6 @@ class UaClient(AbstractSession): ...@@ -780,6 +780,6 @@ class UaClient(AbstractSession):
return response.Parameters.Results return response.Parameters.Results
async def transfer_subscriptions(self, params: ua.TransferSubscriptionsParameters) -> List[ua.TransferResult]: async def transfer_subscriptions(self, params: ua.TransferSubscriptionsParameters) -> List[ua.TransferResult]:
# Subscriptions aren't bound to a Session and can be transfered! # Subscriptions aren't bound to a Session and can be transferred!
# https://reference.opcfoundation.org/Core/Part4/v104/5.13.7/ # https://reference.opcfoundation.org/Core/Part4/v104/5.13.7/
raise NotImplementedError raise NotImplementedError
...@@ -89,7 +89,7 @@ class UaFile: ...@@ -89,7 +89,7 @@ class UaFile:
It is server-dependent whether the written data are persistently It is server-dependent whether the written data are persistently
stored if the session is ended without calling the Close Method with the fileHandle. stored if the session is ended without calling the Close Method with the fileHandle.
Writing an empty or null ByteString returns a Good result code without any Writing an empty or null ByteString returns a Good result code without any
affect on the file. effect on the file.
""" """
_logger.debug("Request to write to file %s", self._file_node) _logger.debug("Request to write to file %s", self._file_node)
if self._write_node is None: if self._write_node is None:
......
...@@ -48,7 +48,7 @@ class State: ...@@ -48,7 +48,7 @@ class State:
class Transition: class Transition:
''' '''
Helperclass for Transitions (TransitionVariableType) Helper class for Transitions (TransitionVariableType)
https://reference.opcfoundation.org/v104/Core/docs/Part5/B.4.4/ https://reference.opcfoundation.org/v104/Core/docs/Part5/B.4.4/
name: type string will be converted automatically to qualifiedname name: type string will be converted automatically to qualifiedname
-> Name is a QualifiedName which uniquely identifies a transition within the StateMachineType. -> Name is a QualifiedName which uniquely identifies a transition within the StateMachineType.
...@@ -57,7 +57,7 @@ class Transition: ...@@ -57,7 +57,7 @@ class Transition:
transitiontime: TransitionTime specifies when the transition occurred. transitiontime: TransitionTime specifies when the transition occurred.
effectivetransitiontime: EffectiveTransitionTime specifies the time when the current state or one of its substates was entered. effectivetransitiontime: EffectiveTransitionTime specifies the time when the current state or one of its substates was entered.
If, for example, a StateA is active and – while active – switches several times between its substates SubA and SubB, If, for example, a StateA is active and – while active – switches several times between its substates SubA and SubB,
then the TransitionTime stays at the point in time where StateA became active whereas the EffectiveTransitionTime changes then the TransitionTime stays at the point in time when StateA became active whereas the EffectiveTransitionTime changes
with each change of a substate. with each change of a substate.
''' '''
def __init__(self, id, name: str=None, number: int=None, node: Node=None): def __init__(self, id, name: str=None, number: int=None, node: Node=None):
...@@ -153,7 +153,7 @@ class StateMachine(object): ...@@ -153,7 +153,7 @@ class StateMachine(object):
elif dn.Text == "EffectiveDisplayName": elif dn.Text == "EffectiveDisplayName":
self._current_state_effective_display_name_node = await self._current_state_node.get_child(["EffectiveDisplayName"]) self._current_state_effective_display_name_node = await self._current_state_node.get_child(["EffectiveDisplayName"])
else: else:
_logger.warning(f"{await statemachine.read_browse_name()} CurrentState Unknown propertie: {dn.Text}") _logger.warning(f"{await statemachine.read_browse_name()} CurrentState Unknown property: {dn.Text}")
if self._optionals: if self._optionals:
self._last_transition_node = await statemachine.get_child(["LastTransition"]) self._last_transition_node = await statemachine.get_child(["LastTransition"])
last_transition_props = await self._last_transition_node.get_properties() last_transition_props = await self._last_transition_node.get_properties()
...@@ -168,7 +168,7 @@ class StateMachine(object): ...@@ -168,7 +168,7 @@ class StateMachine(object):
elif dn.Text == "TransitionTime": elif dn.Text == "TransitionTime":
self._last_transition_transitiontime_node = await self._last_transition_node.get_child(["TransitionTime"]) self._last_transition_transitiontime_node = await self._last_transition_node.get_child(["TransitionTime"])
else: else:
_logger.warning(f"{await statemachine.read_browse_name()} LastTransition Unknown propertie: {dn.Text}") _logger.warning(f"{await statemachine.read_browse_name()} LastTransition Unknown property: {dn.Text}")
self._evgen = await self._server.get_event_generator(self.evtype, self._state_machine_node) self._evgen = await self._server.get_event_generator(self.evtype, self._state_machine_node)
async def change_state(self, state: State, transition: Transition=None, event_msg:Union[str, ua.LocalizedText]=None, severity: int=500): async def change_state(self, state: State, transition: Transition=None, event_msg:Union[str, ua.LocalizedText]=None, severity: int=500):
......
...@@ -228,10 +228,10 @@ from asyncua import ua ...@@ -228,10 +228,10 @@ from asyncua import ua
async def load_type_definitions(server, nodes=None): async def load_type_definitions(server, nodes=None):
""" """
Download xml from given variable node defining custom structures. Download xml from given variable node defining custom structures.
If no node is given, attemps to import variables from all nodes under If no node is given, attempts to import variables from all nodes under
"0:OPC Binary" "0:OPC Binary"
the code is generated and imported on the fly. If you know the structures the code is generated and imported on the fly. If you know the structures
are not going to be modified it might be interresting to copy the generated files are not going to be modified it might be interesting to copy the generated files
and include them in you code and include them in you code
""" """
if nodes is None: if nodes is None:
...@@ -251,7 +251,7 @@ async def load_type_definitions(server, nodes=None): ...@@ -251,7 +251,7 @@ async def load_type_definitions(server, nodes=None):
generator.get_python_classes(structs_dict) generator.get_python_classes(structs_dict)
# same but using a file that is imported. This can be useful for debugging library # same but using a file that is imported. This can be useful for debugging library
# name = node.read_browse_name().Name # name = node.read_browse_name().Name
# Make sure structure names do not contain charaters that cannot be used in Python class file names # Make sure structure names do not contain characters that cannot be used in Python class file names
# name = clean_name(name) # name = clean_name(name)
# name = "structures_" + node.read_browse_name().Name # name = "structures_" + node.read_browse_name().Name
# generator.save_and_import(name + ".py", append_to=structs_dict) # generator.save_and_import(name + ".py", append_to=structs_dict)
...@@ -268,7 +268,7 @@ async def load_type_definitions(server, nodes=None): ...@@ -268,7 +268,7 @@ async def load_type_definitions(server, nodes=None):
continue continue
nodeid = ref_desc_list[0].NodeId nodeid = ref_desc_list[0].NodeId
ua.register_extension_object(name, nodeid, structs_dict[name]) ua.register_extension_object(name, nodeid, structs_dict[name])
# save the typeid if user want to create static file for type definitnion # save the typeid if user want to create static file for type definition
generator.set_typeid(name, nodeid.to_string()) generator.set_typeid(name, nodeid.to_string())
for key, val in structs_dict.items(): for key, val in structs_dict.items():
......
...@@ -120,7 +120,7 @@ async def new_enum( ...@@ -120,7 +120,7 @@ async def new_enum(
def clean_name(name): def clean_name(name):
""" """
Remove characters that might be present in OPC UA structures Remove characters that might be present in OPC UA structures
but cannot be part of of Python class names but cannot be part of Python class names
""" """
if keyword.iskeyword(name): if keyword.iskeyword(name):
return name + "_" return name + "_"
...@@ -383,7 +383,7 @@ async def _recursive_parse_basedatatypes(server, base_node, parent_datatype, new ...@@ -383,7 +383,7 @@ async def _recursive_parse_basedatatypes(server, base_node, parent_datatype, new
for desc in await base_node.get_children_descriptions(refs=ua.ObjectIds.HasSubtype): for desc in await base_node.get_children_descriptions(refs=ua.ObjectIds.HasSubtype):
name = clean_name(desc.BrowseName.Name) name = clean_name(desc.BrowseName.Name)
if parent_datatype not in 'Number': if parent_datatype not in 'Number':
# Don't insert Number alias, they should be allready insert because they have to be basetypes allready # Don't insert Number alias, they should be already insert because they have to be basetypes already
if not hasattr(ua, name): if not hasattr(ua, name):
env = make_basetype_code(name, parent_datatype) env = make_basetype_code(name, parent_datatype)
ua.register_basetype(name, desc.NodeId, env[name]) ua.register_basetype(name, desc.NodeId, env[name])
...@@ -421,7 +421,7 @@ async def _load_base_datatypes(server: Union["Server", "Client"]) -> Any: ...@@ -421,7 +421,7 @@ async def _load_base_datatypes(server: Union["Server", "Client"]) -> Any:
async def load_data_type_definitions(server: Union["Server", "Client"], base_node: Node = None, overwrite_existing=False) -> Dict: async def load_data_type_definitions(server: Union["Server", "Client"], base_node: Node = None, overwrite_existing=False) -> Dict:
""" """
Read DataTypeDefition attribute on all Structure and Enumeration defined Read DataTypeDefinition attribute on all Structure and Enumeration defined
on server and generate Python objects in ua namespace to be used to talk with server on server and generate Python objects in ua namespace to be used to talk with server
""" """
new_objects = await _load_base_datatypes(server) # we need to load all basedatatypes alias first new_objects = await _load_base_datatypes(server) # we need to load all basedatatypes alias first
...@@ -510,7 +510,7 @@ async def load_enums(server: Union["Server", "Client"], base_node: Node = None, ...@@ -510,7 +510,7 @@ async def load_enums(server: Union["Server", "Client"], base_node: Node = None,
name = clean_name(desc.BrowseName.Name) name = clean_name(desc.BrowseName.Name)
if hasattr(ua, name): if hasattr(ua, name):
continue continue
logger.info("Registring Enum %s %s OptionSet=%s", desc.NodeId, name, option_set) logger.info("Registering Enum %s %s OptionSet=%s", desc.NodeId, name, option_set)
edef = await _read_data_type_definition(server, desc) edef = await _read_data_type_definition(server, desc)
if not edef: if not edef:
continue continue
......
""" """
Usefull method and classes not belonging anywhere and depending on asyncua library Useful methods and classes not belonging anywhere and depending on asyncua library
""" """
import uuid import uuid
...@@ -16,7 +16,7 @@ logger = logging.getLogger('__name__') ...@@ -16,7 +16,7 @@ logger = logging.getLogger('__name__')
def value_to_datavalue(val, varianttype=None): def value_to_datavalue(val, varianttype=None):
""" """
convert anyting to a DataValue using varianttype convert anything to a DataValue using varianttype
""" """
if isinstance(val, ua.DataValue): if isinstance(val, ua.DataValue):
return val return val
...@@ -31,7 +31,7 @@ def val_to_string(val, truncate=False): ...@@ -31,7 +31,7 @@ def val_to_string(val, truncate=False):
which should be easy to understand for human which should be easy to understand for human
easy to modify, and not too hard to parse back ....not easy easy to modify, and not too hard to parse back ....not easy
meant for UI or command lines meant for UI or command lines
if truncate is true then huge strings or bytes are tuncated if truncate is true then huge strings or bytes are truncated
""" """
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
...@@ -172,7 +172,7 @@ async def get_node_subtypes(node, nodes=None): ...@@ -172,7 +172,7 @@ async def get_node_subtypes(node, nodes=None):
async def get_node_supertypes(node, includeitself=False, skipbase=True): async def get_node_supertypes(node, includeitself=False, skipbase=True):
""" """
return get all subtype parents of node recursive return get all subtype parents of node recursive
:param node: can be a ua.Node or ua.NodeId :param node: can be an ua.Node or ua.NodeId
:param includeitself: include also node to the list :param includeitself: include also node to the list
:param skipbase don't include the toplevel one :param skipbase don't include the toplevel one
:returns list of ua.Node, top parent first :returns list of ua.Node, top parent first
...@@ -216,7 +216,7 @@ async def is_child_present(node, browsename): ...@@ -216,7 +216,7 @@ async def is_child_present(node, browsename):
return if a browsename is present a child from the provide node return if a browsename is present a child from the provide node
:param node: node wherein to find the browsename :param node: node wherein to find the browsename
:param browsename: browsename to search :param browsename: browsename to search
:returns returne True if the browsename is present else False :returns returns True if the browsename is present else False
""" """
child_descs = await node.get_children_descriptions() child_descs = await node.get_children_descriptions()
for child_desc in child_descs: for child_desc in child_descs:
...@@ -232,7 +232,7 @@ async def data_type_to_variant_type(dtype_node): ...@@ -232,7 +232,7 @@ async def data_type_to_variant_type(dtype_node):
""" """
base = await get_base_data_type(dtype_node) base = await get_base_data_type(dtype_node)
if base.nodeid.Identifier == 29: if base.nodeid.Identifier == 29:
# we have an enumeration, value is a Int32 # we have an enumeration, value is an Int32
return ua.VariantType.Int32 return ua.VariantType.Int32
elif base.nodeid.Identifier in [24, 26, 27, 28]: elif base.nodeid.Identifier in [24, 26, 27, 28]:
# BaseDataType, Number, Integer, UInteger -> Variant # BaseDataType, Number, Integer, UInteger -> Variant
...@@ -277,10 +277,10 @@ async def get_nodes_of_namespace(server, namespaces=None): ...@@ -277,10 +277,10 @@ async def get_nodes_of_namespace(server, namespaces=None):
elif isinstance(namespaces, (str, int)): elif isinstance(namespaces, (str, int)):
namespaces = [namespaces] namespaces = [namespaces]
# make sure all namespace are indexes (if needed convert strings to indexes) # make sure all namespace are indexes (if needed, convert strings to indexes)
namespace_indexes = [n if isinstance(n, int) else ns_available.index(n) for n in namespaces] namespace_indexes = [n if isinstance(n, int) else ns_available.index(n) for n in namespaces]
# filter nodeis based on the provide namespaces and convert the nodeid to a node # filter node is based on the provided namespaces and convert the nodeid to a node
nodes = [ nodes = [
server.get_node(nodeid) for nodeid in server.iserver.aspace.keys() server.get_node(nodeid) for nodeid in server.iserver.aspace.keys()
if nodeid.NamespaceIndex != 0 and nodeid.NamespaceIndex in namespace_indexes if nodeid.NamespaceIndex != 0 and nodeid.NamespaceIndex in namespace_indexes
...@@ -297,7 +297,7 @@ def get_default_value(uatype): ...@@ -297,7 +297,7 @@ def get_default_value(uatype):
def data_type_to_string(dtype): def data_type_to_string(dtype):
# we could just display browse name of node but it requires a query # we could just display browse name of node, but it requires a query
if dtype.NamespaceIndex == 0 and dtype.Identifier in ua.ObjectIdNames: if dtype.NamespaceIndex == 0 and dtype.Identifier in ua.ObjectIdNames:
string = ua.ObjectIdNames[dtype.Identifier] string = ua.ObjectIdNames[dtype.Identifier]
else: else:
......
...@@ -322,7 +322,7 @@ class XmlExporter: ...@@ -322,7 +322,7 @@ class XmlExporter:
elif isinstance(sdef, ua.EnumDefinition): elif isinstance(sdef, ua.EnumDefinition):
self._enum_fields_to_etree(sdef_el, sdef) self._enum_fields_to_etree(sdef_el, sdef)
else: else:
self.logger.warning("Unknown DataTypeSpecification elemnt: %s", sdef) self.logger.warning("Unknown DataTypeSpecification element: %s", sdef)
def _structure_fields_to_etree(self, sdef_el, sdef): def _structure_fields_to_etree(self, sdef_el, sdef):
for field in sdef.Fields: for field in sdef.Fields:
...@@ -447,7 +447,7 @@ class XmlExporter: ...@@ -447,7 +447,7 @@ class XmlExporter:
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
if dtype.NamespaceIndex == 0 and dtype.Identifier <= 21: if dtype.NamespaceIndex == 0 and dtype.Identifier <= 21:
elname = "uax:ListOf" + type_name elname = "uax:ListOf" + type_name
else: # this is an extentionObject: else: # this is an extensionObject:
elname = "uax:ListOfExtensionObject" elname = "uax:ListOfExtensionObject"
list_el = Et.SubElement(el, elname) list_el = Et.SubElement(el, elname)
...@@ -489,9 +489,9 @@ class XmlExporter: ...@@ -489,9 +489,9 @@ class XmlExporter:
async def _all_fields_to_etree(self, struct_el, val): async def _all_fields_to_etree(self, struct_el, val):
# TODO: adding the 'ua' module to the globals to resolve the type hints might not be enough. # TODO: adding the 'ua' module to the globals to resolve the type hints might not be enough.
# its possible that the type annotations also refere to classes defined in other modules. # it is possible that the type annotations also refere to classes defined in other modules.
for field in fields_with_resolved_types(val, globalns={"ua": ua}): for field in fields_with_resolved_types(val, globalns={"ua": ua}):
# FIXME; what happend if we have a custom type which is not part of ObjectIds??? # FIXME; what happened if we have a custom type which is not part of ObjectIds???
if field.name == "Encoding": if field.name == "Encoding":
continue continue
type_name = type_string_from_type(field.type) type_name = type_string_from_type(field.type)
......
...@@ -21,7 +21,7 @@ class XmlImporter: ...@@ -21,7 +21,7 @@ class XmlImporter:
def __init__(self, server, strict_mode=True): def __init__(self, server, strict_mode=True):
''' '''
strict_mode: stop on a error, if False only a error message is logged, strict_mode: stop on an error, if False only an error message is logged,
but the import continues but the import continues
''' '''
self.parser = None self.parser = None
...@@ -279,7 +279,7 @@ class XmlImporter: ...@@ -279,7 +279,7 @@ class XmlImporter:
def _migrate_ns(self, obj: Union[ua.NodeId, ua.QualifiedName]) -> Union[ua.NodeId, ua.QualifiedName]: def _migrate_ns(self, obj: Union[ua.NodeId, ua.QualifiedName]) -> Union[ua.NodeId, ua.QualifiedName]:
""" """
Check if the index of nodeid or browsename given in the xml model file Check if the index of nodeid or browsename given in the xml model file
must be converted to a already existing namespace id based on the files must be converted to an already existing namespace id based on the files
namespace uri namespace uri
:returns: NodeId (str) :returns: NodeId (str)
......
...@@ -352,8 +352,8 @@ class XMLParser: ...@@ -352,8 +352,8 @@ class XMLParser:
def _parse_list_of_extension_object(self, el): def _parse_list_of_extension_object(self, el):
""" """
Parse a uax:ListOfExtensionObject Value Parse an uax:ListOfExtensionObject Value
Return an list of ExtObj Return a list of ExtObj
""" """
value = [] value = []
for extension_object in el: for extension_object in el:
......
...@@ -66,4 +66,3 @@ class SimpleRoleRuleset(PermissionRuleset): ...@@ -66,4 +66,3 @@ class SimpleRoleRuleset(PermissionRuleset):
return True return True
else: else:
return False return False
...@@ -538,7 +538,7 @@ class SecurityPolicyBasic128Rsa15(SecurityPolicy): ...@@ -538,7 +538,7 @@ class SecurityPolicyBasic128Rsa15(SecurityPolicy):
- CertificateSignatureAlgorithm - Sha1 - CertificateSignatureAlgorithm - Sha1
If a certificate or any certificate in the chain is not signed with If a certificate or any certificate in the chain is not signed with
a hash that is Sha1 or stronger then the certificate shall be rejected. a hash that is Sha1 or stronger than the certificate shall be rejected.
""" """
URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15" URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"
...@@ -626,7 +626,7 @@ class SecurityPolicyBasic256(SecurityPolicy): ...@@ -626,7 +626,7 @@ class SecurityPolicyBasic256(SecurityPolicy):
- CertificateSignatureAlgorithm - Sha1 - CertificateSignatureAlgorithm - Sha1
If a certificate or any certificate in the chain is not signed with If a certificate or any certificate in the chain is not signed with
a hash that is Sha1 or stronger then the certificate shall be rejected. a hash that is Sha1 or stronger than the certificate shall be rejected.
""" """
URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256" URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256"
......
...@@ -49,7 +49,7 @@ class InternalServer: ...@@ -49,7 +49,7 @@ class InternalServer:
self.endpoints = [] self.endpoints = []
self._channel_id_counter = 5 self._channel_id_counter = 5
self.allow_remote_admin = True self.allow_remote_admin = True
self.disabled_clock = False # for debugging we may want to disable clock that writes too much in log self.disabled_clock = False # for debugging, we may want to disable clock that writes too much in log
self._known_servers = {} # used if we are a discovery server self._known_servers = {} # used if we are a discovery server
self.certificate = None self.certificate = None
self.private_key = None self.private_key = None
...@@ -297,7 +297,7 @@ class InternalServer: ...@@ -297,7 +297,7 @@ class InternalServer:
async def write_attribute_value(self, nodeid, datavalue, attr=ua.AttributeIds.Value): async def write_attribute_value(self, nodeid, datavalue, attr=ua.AttributeIds.Value):
""" """
directly write datavalue to the Attribute, bypassing some checks and structure creation directly write datavalue to the Attribute, bypassing some checks and structure creation,
so it is a little faster so it is a little faster
""" """
await self.aspace.write_attribute_value(nodeid, attr, datavalue) await self.aspace.write_attribute_value(nodeid, attr, datavalue)
......
...@@ -56,7 +56,7 @@ class Server: ...@@ -56,7 +56,7 @@ class Server:
During startup the standard address space will be constructed, which may be During startup the standard address space will be constructed, which may be
time-consuming when running a server on a less powerful device (e.g. a time-consuming when running a server on a less powerful device (e.g. a
Raspberry Pi). In order to improve startup performance, a optional path to a Raspberry Pi). In order to improve startup performance, an optional path to a
cache file can be passed to the server constructor. cache file can be passed to the server constructor.
If the parameter is defined, the address space will be loaded from the If the parameter is defined, the address space will be loaded from the
cache file or the file will be created if it does not exist yet. cache file or the file will be created if it does not exist yet.
...@@ -106,7 +106,7 @@ class Server: ...@@ -106,7 +106,7 @@ class Server:
self._permission_ruleset = None self._permission_ruleset = None
self._policyIDs = ["Anonymous", "Basic256Sha256", "Username", "Aes128Sha256RsaOaep"] self._policyIDs = ["Anonymous", "Basic256Sha256", "Username", "Aes128Sha256RsaOaep"]
self.certificate = None self.certificate = None
# Use accectable limits # Use acceptable limits
buffer_sz = 65535 buffer_sz = 65535
max_msg_sz = 100 * 1024 * 1024 # 100mb max_msg_sz = 100 * 1024 * 1024 # 100mb
self.limits = TransportLimits( self.limits = TransportLimits(
...@@ -234,7 +234,7 @@ class Server: ...@@ -234,7 +234,7 @@ class Server:
async def set_application_uri(self, uri: str): async def set_application_uri(self, uri: str):
""" """
Set application/server URI. Set application/server URI.
This uri is supposed to be unique. If you intent to register This uri is supposed to be unique. If you intend to register
your server to a discovery server, it really should be unique in your server to a discovery server, it really should be unique in
your system! your system!
default is : "urn:freeopcua:python:server" default is : "urn:freeopcua:python:server"
...@@ -728,7 +728,7 @@ class Server: ...@@ -728,7 +728,7 @@ class Server:
async def write_attribute_value(self, nodeid, datavalue, attr=ua.AttributeIds.Value): async def write_attribute_value(self, nodeid, datavalue, attr=ua.AttributeIds.Value):
""" """
directly write datavalue to the Attribute, bypasing some checks and structure creation directly write datavalue to the Attribute, bypassing some checks and structure creation,
so it is a little faster so it is a little faster
""" """
return await self.iserver.write_attribute_value(nodeid, datavalue, attr) return await self.iserver.write_attribute_value(nodeid, datavalue, attr)
......
...@@ -259,7 +259,7 @@ class UaProcessor: ...@@ -259,7 +259,7 @@ class UaProcessor:
self.send_response(requesthdr.RequestHandle, seqhdr, response) self.send_response(requesthdr.RequestHandle, seqhdr, response)
return False return False
else: else:
# All services that requere a active session # All services that require an active session
if not self.session: if not self.session:
_logger.info("Request service that need a session (%s)", user) _logger.info("Request service that need a session (%s)", user)
raise ServiceError(ua.StatusCodes.BadSessionIdInvalid) raise ServiceError(ua.StatusCodes.BadSessionIdInvalid)
......
...@@ -602,7 +602,7 @@ async def _uaserver(): ...@@ -602,7 +602,7 @@ async def _uaserver():
description="Run an example OPC-UA server. By importing xml definition and using uawrite " 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" " 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 # we set up a server, this is a bit different from other tool, so we do not reuse common arguments
parser.add_argument( parser.add_argument(
"-u", "-u",
"--url", "--url",
......
...@@ -278,14 +278,14 @@ def create_dataclass_serializer(dataclazz): ...@@ -278,14 +278,14 @@ def create_dataclass_serializer(dataclazz):
"""Given a dataclass, return a function that serializes instances of this dataclass""" """Given a dataclass, return a function that serializes instances of this dataclass"""
data_fields = fields(dataclazz) data_fields = fields(dataclazz)
# TODO: adding the 'ua' module to the globals to resolve the type hints might not be enough. # TODO: adding the 'ua' module to the globals to resolve the type hints might not be enough.
# its possible that the type annotations also refere to classes defined in other modules. # it is possible that the type annotations also refere to classes defined in other modules.
resolved_fieldtypes = typing.get_type_hints(dataclazz, {'ua': ua}) resolved_fieldtypes = typing.get_type_hints(dataclazz, {'ua': ua})
for f in data_fields: for f in data_fields:
f.type = resolved_fieldtypes[f.name] f.type = resolved_fieldtypes[f.name]
if issubclass(dataclazz, ua.UaUnion): if issubclass(dataclazz, ua.UaUnion):
# Union is a class with Encoding and Value field # Union is a class with Encoding and Value field
# the value is depended of encoding # the value depends on encoding
encoding_funcs = [field_serializer(t, dataclazz) for t in dataclazz._union_types] encoding_funcs = [field_serializer(t, dataclazz) for t in dataclazz._union_types]
def union_serialize(obj): def union_serialize(obj):
......
...@@ -13,9 +13,9 @@ OPC_TCP_SCHEME = 'opc.tcp' ...@@ -13,9 +13,9 @@ OPC_TCP_SCHEME = 'opc.tcp'
@dataclass @dataclass
class Hello: class Hello:
ProtocolVersion: uatypes.UInt32 = 0 ProtocolVersion: uatypes.UInt32 = 0
# the following values couldbe set to 0 (meaning no limits) # the following values could be set to 0 (meaning no limits)
# unfortunaltely many servers do not support it # unfortunately many servers do not support it
# even newer version of prosys are broken # even newer version of prosys is broken,
# so we set then to a high value known to work most places # so we set then to a high value known to work most places
ReceiveBufferSize: uatypes.UInt32 = 2**31 - 1 ReceiveBufferSize: uatypes.UInt32 = 2**31 - 1
SendBufferSize: uatypes.UInt32 = 2**31 - 1 SendBufferSize: uatypes.UInt32 = 2**31 - 1
...@@ -111,7 +111,7 @@ class SequenceHeader: ...@@ -111,7 +111,7 @@ class SequenceHeader:
class CryptographyNone: class CryptographyNone:
""" """
Base class for symmetric/asymmetric cryprography Base class for symmetric/asymmetric cryptography
""" """
def __init__(self): def __init__(self):
pass pass
...@@ -275,7 +275,7 @@ class ReferenceTypeAttributes(auto.ReferenceTypeAttributes): ...@@ -275,7 +275,7 @@ class ReferenceTypeAttributes(auto.ReferenceTypeAttributes):
# FIXME: changes in that class donnot seem to be part of spec as of 1.04 # FIXME: changes in that class donnot seem to be part of spec as of 1.04
#not sure what the spec expect, maybe DataTypeDefinition must be set using an extra call... # not sure what the spec expect, maybe DataTypeDefinition must be set using an extra call...
# maybe it will be part of spec in 1.05??? no ideas # maybe it will be part of spec in 1.05??? no ideas
@dataclass @dataclass
class DataTypeAttributes(auto.DataTypeAttributes): class DataTypeAttributes(auto.DataTypeAttributes):
...@@ -285,7 +285,7 @@ class DataTypeAttributes(auto.DataTypeAttributes): ...@@ -285,7 +285,7 @@ class DataTypeAttributes(auto.DataTypeAttributes):
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract | ana.DataTypeDefinition self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract | ana.DataTypeDefinition
# we now need to register DataTypeAttributes since we added a new attritbute # we now need to register DataTypeAttributes since we added a new attribute
nid = uatypes.FourByteNodeId(auto.ObjectIds.DataTypeAttributes_Encoding_DefaultBinary) nid = uatypes.FourByteNodeId(auto.ObjectIds.DataTypeAttributes_Encoding_DefaultBinary)
uatypes.extension_objects_by_typeid[nid] = DataTypeAttributes uatypes.extension_objects_by_typeid[nid] = DataTypeAttributes
uatypes.extension_object_typeids['DataTypeAttributes'] = nid uatypes.extension_object_typeids['DataTypeAttributes'] = nid
......
...@@ -149,7 +149,7 @@ class Null: # Null(NoneType) is not supported in Python ...@@ -149,7 +149,7 @@ class Null: # Null(NoneType) is not supported in Python
pass pass
class String: # Passing None as arg will result in unepected behaviour so disabling class String: # Passing None as arg will result in unexpected behaviour so disabling
pass pass
...@@ -206,7 +206,7 @@ class ValueRank(IntEnum): ...@@ -206,7 +206,7 @@ class ValueRank(IntEnum):
""" """
Defines dimensions of a variable. Defines dimensions of a variable.
This enum does not support all cases since ValueRank support any n>0 This enum does not support all cases since ValueRank support any n>0
but since it is an IntEnum it can be replace by a normal int but since it is an IntEnum it can be replaced by a normal int
""" """
ScalarOrOneDimension = -3 ScalarOrOneDimension = -3
...@@ -405,7 +405,7 @@ class NodeId: ...@@ -405,7 +405,7 @@ class NodeId:
Args: Args:
identifier: The identifier might be an int, a string, bytes or a Guid identifier: The identifier might be an int, a string, bytes or a Guid
namespaceidx(int): The index of the namespace namespaceidx(int): The index of the namespace
nodeidtype(NodeIdType): The type of the nodeid if it cannot be guess or you want something nodeidtype(NodeIdType): The type of the nodeid if it cannot be guessed, or you want something
special like twobyte nodeid or fourbytenodeid special like twobyte nodeid or fourbytenodeid
...@@ -644,10 +644,10 @@ class QualifiedName: ...@@ -644,10 +644,10 @@ class QualifiedName:
object.__setattr__(self, "NamespaceIndex", NamespaceIndex) object.__setattr__(self, "NamespaceIndex", NamespaceIndex)
if isinstance(self.NamespaceIndex, str) and isinstance(self.Name, int): if isinstance(self.NamespaceIndex, str) and isinstance(self.Name, int):
# originally the order or argument was inversed, try to support it # originally the order or argument was inversed, try to support it
logger.warning("QualifiedName are str, int, while int, str is expected, swithcing") logger.warning("QualifiedName are str, int, while int, str is expected, switching")
if not isinstance(self.NamespaceIndex, int) or not isinstance(self.Name, (str, type(None))): if not isinstance(self.NamespaceIndex, int) or not isinstance(self.Name, (str, type(None))):
raise ValueError(f"QualifiedName constructore args have wrong types, {self}") raise ValueError(f"QualifiedName constructor args have wrong types, {self}")
def to_string(self): def to_string(self):
return f"{self.NamespaceIndex}:{self.Name}" return f"{self.NamespaceIndex}:{self.Name}"
...@@ -677,7 +677,7 @@ class LocalizedText: ...@@ -677,7 +677,7 @@ class LocalizedText:
Text: Optional[String] = None Text: Optional[String] = None
def __init__(self, Text=None, Locale=None): def __init__(self, Text=None, Locale=None):
# need to write init method since args ar inverted in original implementataion # need to write init method since args ar inverted in original implementation
object.__setattr__(self, "Text", Text) object.__setattr__(self, "Text", Text)
object.__setattr__(self, "Locale", Locale) object.__setattr__(self, "Locale", Locale)
...@@ -820,7 +820,7 @@ class Variant: ...@@ -820,7 +820,7 @@ class Variant:
""" """
Create an OPC-UA Variant object. Create an OPC-UA Variant object.
if no argument a Null Variant is created. if no argument a Null Variant is created.
if not variant type is given, attemps to guess type from python type if not variant type is given, attempts to guess type from python type
if a variant is given as value, the new objects becomes a copy of the argument if a variant is given as value, the new objects becomes a copy of the argument
:ivar Value: :ivar Value:
...@@ -828,9 +828,9 @@ class Variant: ...@@ -828,9 +828,9 @@ class Variant:
:ivar VariantType: :ivar VariantType:
:vartype VariantType: VariantType :vartype VariantType: VariantType
:ivar Dimension: :ivar Dimension:
:vartype Dimensions: The length of each dimensions. Make the variant a Matrix :vartype Dimensions: The length of each dimension. Make the variant a Matrix
:ivar is_array: :ivar is_array:
:vartype is_array: If the variant is an array. Always True if Dimension is specificied :vartype is_array: If the variant is an array. Always True if Dimension is specified
""" """
# FIXME: typing is wrong here # FIXME: typing is wrong here
...@@ -965,7 +965,7 @@ def get_shape(mylist): ...@@ -965,7 +965,7 @@ def get_shape(mylist):
return dims return dims
# For completness, these datatypes are abstract! # For completeness, these datatypes are abstract!
# If they are used in structs, abstract types are either Variant or ExtensionObjects. # If they are used in structs, abstract types are either Variant or ExtensionObjects.
# If they only contain basic types (int16, float, double..) they are Variants # If they only contain basic types (int16, float, double..) they are Variants
UInteger = Variant UInteger = Variant
...@@ -1087,7 +1087,7 @@ def get_default_value(vtype): ...@@ -1087,7 +1087,7 @@ def get_default_value(vtype):
if vtype == VariantType.Guid: if vtype == VariantType.Guid:
return uuid.uuid4() return uuid.uuid4()
if vtype == VariantType.XmlElement: if vtype == VariantType.XmlElement:
return None # Not sure this is correct return None # Not sure if this is correct
if vtype == VariantType.NodeId: if vtype == VariantType.NodeId:
return NodeId() return NodeId()
if vtype == VariantType.ExpandedNodeId: if vtype == VariantType.ExpandedNodeId:
...@@ -1114,9 +1114,9 @@ basetype_datatypes = {} ...@@ -1114,9 +1114,9 @@ basetype_datatypes = {}
# register of alias of basetypes # register of alias of basetypes
def register_basetype(name, nodeid, class_type): def register_basetype(name, nodeid, class_type):
""" """
Register a new allias of basetypes for automatic decoding and make them available in ua module Register a new alias of basetypes for automatic decoding and make them available in ua module
""" """
logger.info("registring new basetype alias: %s %s %s", name, nodeid, class_type) logger.info("registering new basetype alias: %s %s %s", name, nodeid, class_type)
basetype_by_datatype[nodeid] = name basetype_by_datatype[nodeid] = name
basetype_datatypes[class_type] = nodeid basetype_datatypes[class_type] = nodeid
import asyncua.ua import asyncua.ua
...@@ -1133,7 +1133,7 @@ def register_enum(name, nodeid, class_type): ...@@ -1133,7 +1133,7 @@ def register_enum(name, nodeid, class_type):
""" """
Register a new enum for automatic decoding and make them available in ua module Register a new enum for automatic decoding and make them available in ua module
""" """
logger.info("registring new enum: %s %s %s", name, nodeid, class_type) logger.info("registering new enum: %s %s %s", name, nodeid, class_type)
enums_by_datatype[nodeid] = class_type enums_by_datatype[nodeid] = class_type
enums_datatypes[class_type] = nodeid enums_datatypes[class_type] = nodeid
import asyncua.ua import asyncua.ua
...@@ -1141,7 +1141,7 @@ def register_enum(name, nodeid, class_type): ...@@ -1141,7 +1141,7 @@ def register_enum(name, nodeid, class_type):
setattr(asyncua.ua, name, class_type) setattr(asyncua.ua, name, class_type)
# These dictionnaries are used to register extensions classes for automatic # These dictionaries are used to register extensions classes for automatic
# decoding and encoding # decoding and encoding
extension_objects_by_datatype = {} # Dict[Datatype, type] extension_objects_by_datatype = {} # Dict[Datatype, type]
extension_objects_by_typeid = {} # Dict[EncodingId, type] extension_objects_by_typeid = {} # Dict[EncodingId, type]
...@@ -1154,7 +1154,7 @@ def register_extension_object(name, encoding_nodeid, class_type, datatype_nodeid ...@@ -1154,7 +1154,7 @@ def register_extension_object(name, encoding_nodeid, class_type, datatype_nodeid
Register a new extension object for automatic decoding and make them available in ua module Register a new extension object for automatic decoding and make them available in ua module
""" """
logger.info( logger.info(
"registring new extension object: %s %s %s %s", "registering new extension object: %s %s %s %s",
name, name,
encoding_nodeid, encoding_nodeid,
class_type, class_type,
......
...@@ -24,12 +24,12 @@ async def main(): ...@@ -24,12 +24,12 @@ async def main():
await server.init() await server.init()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
# setup our own namespace, not really necessary but should as spec # set up our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = await server.register_namespace(uri) idx = await server.register_namespace(uri)
# populating our address space # populating our address space
# setup a variable far too big for our limits # set up a variable far too big for our limits
test_string = b'a' * (100 * 1024 * 1024) test_string = b'a' * (100 * 1024 * 1024)
test_string = b'a' * 100 * 1024 test_string = b'a' * 100 * 1024
print("LENGTH VAR", len(test_string)) print("LENGTH VAR", len(test_string))
......
...@@ -53,14 +53,14 @@ async def main(): ...@@ -53,14 +53,14 @@ async def main():
# logger = logging.getLogger("asyncua.subscription_service") # logger = logging.getLogger("asyncua.subscription_service")
# logger.setLevel(logging.DEBUG) # logger.setLevel(logging.DEBUG)
# now setup our server # now set up our server
server = Server() server = Server()
await server.init() await server.init()
# server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/") # server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
server.set_server_name("FreeOpcUa Example Server") server.set_server_name("FreeOpcUa Example Server")
# setup our own namespace # set up our own namespace
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = await server.register_namespace(uri) idx = await server.register_namespace(uri)
......
...@@ -17,7 +17,7 @@ async def main(): ...@@ -17,7 +17,7 @@ async def main():
await server.init() await server.init()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
# setup our own namespace, not really necessary but should as spec # set up our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = await server.register_namespace(uri) idx = await server.register_namespace(uri)
......
...@@ -11,7 +11,7 @@ from asyncua import ua, Server ...@@ -11,7 +11,7 @@ from asyncua import ua, Server
# The advantage of this is that the software can be designed in a tool like UA Modeler. Then with minimal setup, a # The advantage of this is that the software can be designed in a tool like UA Modeler. Then with minimal setup, a
# python program will import the XML and mirror all the objects in the software design. After this mirroring is achieved # python program will import the XML and mirror all the objects in the software design. After this mirroring is achieved
# the user can focus on programming in python knowing that all all data from UA clients will reach the python object, # the user can focus on programming in python knowing that all data from UA clients will reach the python object,
# and all data that needs to be output to the server can be published from the python object. # and all data that needs to be output to the server can be published from the python object.
# #
# Be aware that subscription calls are asynchronous. # Be aware that subscription calls are asynchronous.
...@@ -72,7 +72,7 @@ class UaObject(object): ...@@ -72,7 +72,7 @@ class UaObject(object):
class MyObj(UaObject): class MyObj(UaObject):
""" """
Definition of OPC UA object which represents a object to be mirrored in python Definition of OPC UA object which represents an object to be mirrored in python
This class mirrors it's UA counterpart and semi-configures itself according to the UA model (generally from XML) This class mirrors it's UA counterpart and semi-configures itself according to the UA model (generally from XML)
""" """
def __init__(self, asyncua_server, ua_node): def __init__(self, asyncua_server, ua_node):
...@@ -102,7 +102,7 @@ if __name__ == "__main__": ...@@ -102,7 +102,7 @@ if __name__ == "__main__":
server = Server() server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
# setup our own namespace, not really necessary but should as spec # set up our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri) idx = server.register_namespace(uri)
......
...@@ -28,7 +28,7 @@ async def main(): ...@@ -28,7 +28,7 @@ async def main():
await server.init() await server.init()
server.set_endpoint('opc.tcp://example-endpoint.freeopcua.github.com:32000/freeopcua/server/') server.set_endpoint('opc.tcp://example-endpoint.freeopcua.github.com:32000/freeopcua/server/')
# setup our own namespace, not really necessary but should as spec # set up our own namespace, not really necessary but should as spec
uri = 'http://examples.freeopcua.github.io' uri = 'http://examples.freeopcua.github.io'
idx = await server.register_namespace(uri) idx = await server.register_namespace(uri)
......
...@@ -13,7 +13,7 @@ if __name__ == "__main__": ...@@ -13,7 +13,7 @@ if __name__ == "__main__":
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
idx = await server.register_namespace("http://examples.freeopcua.github.io") idx = await server.register_namespace("http://examples.freeopcua.github.io")
# get a instance of the StateMachine-Class def "__init__(self, server=None, parent=None, idx=None, name=None):" # get an instance of the StateMachine-Class def "__init__(self, server=None, parent=None, idx=None, name=None):"
mystatemachine = StateMachine(server, server.nodes.objects, idx, "StateMachine") mystatemachine = StateMachine(server, server.nodes.objects, idx, "StateMachine")
# call statemachine.install() to instantiate the statemachinetype (with or without optional nodes) # call statemachine.install() to instantiate the statemachinetype (with or without optional nodes)
await mystatemachine.install(optionals=True) await mystatemachine.install(optionals=True)
...@@ -22,7 +22,7 @@ if __name__ == "__main__": ...@@ -22,7 +22,7 @@ if __name__ == "__main__":
# if the state node already exist for example from xml model you can assign it here: node=<StateNode> # if the state node already exist for example from xml model you can assign it here: node=<StateNode>
state1 = State("State-Id-1", "Idle", 1) state1 = State("State-Id-1", "Idle", 1)
# adds the state (StateType) to the statemachine childs - this is optional! # adds the state (StateType) to the statemachine childs - this is optional!
await mystatemachine.add_state(state1, state_type=ua.NodeId(2309, 0)) #this is a init state -> InitialStateType: ua.NodeId(2309, 0) await mystatemachine.add_state(state1, state_type=ua.NodeId(2309, 0)) #this is an init state -> InitialStateType: ua.NodeId(2309, 0)
state2 = State("State-Id-2", "Loading", 2) state2 = State("State-Id-2", "Loading", 2)
await mystatemachine.add_state(state2) await mystatemachine.add_state(state2)
state3 = State("State-Id-3", "Initializing", 3) state3 = State("State-Id-3", "Initializing", 3)
...@@ -32,7 +32,7 @@ if __name__ == "__main__": ...@@ -32,7 +32,7 @@ if __name__ == "__main__":
state5 = State("State-Id-5", "Finished", 5) state5 = State("State-Id-5", "Finished", 5)
await mystatemachine.add_state(state5) await mystatemachine.add_state(state5)
# setup your transition helperclass # set up your transition helperclass
# if the transition node already exist for example from xml model you can assign it here: node=<TransitionNode> # if the transition node already exist for example from xml model you can assign it here: node=<TransitionNode>
trans1 = Transition("Transition-Id-1", "to Idle", 1) trans1 = Transition("Transition-Id-1", "to Idle", 1)
# adds the transition (TransitionType) to the statemachine childs - this is optional! # adds the transition (TransitionType) to the statemachine childs - this is optional!
......
...@@ -59,7 +59,7 @@ if __name__ == "__main__": ...@@ -59,7 +59,7 @@ if __name__ == "__main__":
#var.write_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type #var.write_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type
#var.write_value(3.9) # set node value using implicit data type #var.write_value(3.9) # set node value using implicit data type
# gettting our namespace idx # getting our namespace idx
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = client.get_namespace_index(uri) idx = client.get_namespace_index(uri)
......
...@@ -24,8 +24,8 @@ if __name__ == "__main__": ...@@ -24,8 +24,8 @@ if __name__ == "__main__":
with Client("opc.tcp://localhost:53530/OPCUA/SimulationServer/") as client: with Client("opc.tcp://localhost:53530/OPCUA/SimulationServer/") as client:
root = client.nodes.root root = client.nodes.root
print("Root is", root) print("Root is", root)
print("childs of root are: ", root.get_children()) print("children of root are: ", root.get_children())
print("name of root is", root.read_browse_name()) print("name of root is", root.read_browse_name())
objects = client.nodes.objects objects = client.nodes.objects
print("childs og objects are: ", objects.get_children()) print("children og objects are: ", objects.get_children())
embed() embed()
...@@ -83,7 +83,7 @@ if __name__ == "__main__": ...@@ -83,7 +83,7 @@ if __name__ == "__main__":
#logger = logging.getLogger("opcua.uaprocessor") #logger = logging.getLogger("opcua.uaprocessor")
# logger.setLevel(logging.DEBUG) # logger.setLevel(logging.DEBUG)
with ThreadLoop() as tloop: with ThreadLoop() as tloop:
# now setup our server # now set up our server
server = Server(tloop=tloop) server = Server(tloop=tloop)
#server.disable_clock() #server.disable_clock()
#server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/") #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
...@@ -95,7 +95,7 @@ if __name__ == "__main__": ...@@ -95,7 +95,7 @@ if __name__ == "__main__":
ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
ua.SecurityPolicyType.Basic256Sha256_Sign]) ua.SecurityPolicyType.Basic256Sha256_Sign])
# setup our own namespace # set up our own namespace
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri) idx = server.register_namespace(uri)
print("IDX", idx) print("IDX", idx)
...@@ -142,7 +142,7 @@ if __name__ == "__main__": ...@@ -142,7 +142,7 @@ if __name__ == "__main__":
# starting! # starting!
with server: with server:
print("Available loggers are: ", logging.Logger.manager.loggerDict.keys()) print("Available loggers are: ", logging.Logger.manager.loggerDict.keys())
vup = VarUpdater(mysin) # just a stupide class update a variable vup = VarUpdater(mysin) # just a stupid class updating a variable
vup.start() vup.start()
# enable following if you want to subscribe to nodes on server side # enable following if you want to subscribe to nodes on server side
...@@ -151,12 +151,12 @@ if __name__ == "__main__": ...@@ -151,12 +151,12 @@ if __name__ == "__main__":
#handle = sub.subscribe_data_change(myvar) #handle = sub.subscribe_data_change(myvar)
# trigger event, all subscribed clients wil receive it # trigger event, all subscribed clients wil receive it
var = myarrayvar.read_value() # return a ref to value in db server side! not a copy! var = 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 = copy.copy(var) # WARNING: we need to copy before writing again, otherwise no data change event will be generated
var.append(9.3) var.append(9.3)
myarrayvar.write_value(var) myarrayvar.write_value(var)
mydevice_var.write_value("Running") mydevice_var.write_value("Running")
myevgen.trigger(message="This is BaseEvent") myevgen.trigger(message="This is BaseEvent")
server.write_attribute_value(myvar.nodeid, ua.DataValue(9.9)) # Server side write method which is a but faster than using write server.write_attribute_value(myvar.nodeid, ua.DataValue(9.9)) # Server side write method which is a bit faster than using write
embed() embed()
vup.stop() vup.stop()
...@@ -7,11 +7,11 @@ from asyncua.sync import Server ...@@ -7,11 +7,11 @@ from asyncua.sync import Server
if __name__ == "__main__": if __name__ == "__main__":
# setup our server # set up our server
server = Server() server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
# setup our own namespace, not really necessary but should as spec # set up our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io" uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri) idx = server.register_namespace(uri)
...@@ -30,5 +30,5 @@ if __name__ == "__main__": ...@@ -30,5 +30,5 @@ if __name__ == "__main__":
count += 0.1 count += 0.1
myvar.write_value(count) myvar.write_value(count)
finally: finally:
#close connection, remove subcsriptions, etc #close connection, remove subscriptions, etc
server.stop() server.stop()
...@@ -21,7 +21,7 @@ def bump_version(): ...@@ -21,7 +21,7 @@ def bump_version():
def release(): def release():
v = bump_version() v = bump_version()
ans = input("version bumped, commiting?(Y/n)") ans = input("version bumped, committing?(Y/n)")
if ans in ("", "y", "yes"): if ans in ("", "y", "yes"):
os.system("git add setup.py") os.system("git add setup.py")
os.system(f"git commit -m 'new release v{v}'") os.system(f"git commit -m 'new release v{v}'")
......
...@@ -13,7 +13,7 @@ _logger = getLogger(__name__) ...@@ -13,7 +13,7 @@ _logger = getLogger(__name__)
IgnoredEnums = [] IgnoredEnums = []
IgnoredStructs = [] IgnoredStructs = []
# by default we split requests and respons in header and parameters, but some are so simple we do not split them # by default, we split requests and responses in header and parameters, but some are so simple we do not split them
NoSplitStruct = [ NoSplitStruct = [
"GetEndpointsResponse", "GetEndpointsResponse",
"CloseSessionRequest", "CloseSessionRequest",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment