def __init__(self, isession, etype=ua.ObjectIds.BaseEventType, source=ua.ObjectIds.Server): self.isession = isession if isinstance(etype, Node): self.node = etype elif isinstance(etype, ua.NodeId): self.node = Node(self.isession, etype) else: self.node = Node(self.isession, ua.NodeId(etype)) self.set_members_from_node(self.node) if isinstance(source, Node): self.SourceNode = source.NodeId elif isinstance(etype, ua.NodeId): self.SourceNode = source.NodeId else: self.SourceNode = ua.NodeId(source) # set some default values for attributes from BaseEventType, thus that all event must have self.EventId = uuid.uuid4().bytes self.EventType = self.node.nodeid self.LocaleTime = datetime.now() self.ReceiveTime = datetime.now() self.Time = datetime.now() self.Message = ua.LocalizedText() self.Severity = ua.Variant(1, ua.VariantType.UInt16) self.SourceName = "Server" # og set some node attributed we also are expected to have self.BrowseName = self.node.get_browse_name() self.DisplayName = self.node.get_display_name() self.NodeId = self.node.nodeid self.NodeClass = self.node.get_node_class() self.Description = self.node.get_description()
def subscribe_events(self, sourcenode=ua.ObjectIds.Server, evtypes=ua.ObjectIds.BaseEventType, evfilter=None, queuesize=0): """ Subscribe to events from a node. Default node is Server node. In most servers the server node is the only one you can subscribe to. if evtypes is not provided, evtype defaults to BaseEventType if evtypes is a list or tuple of custom event types, the events will be filtered to the supplied types Return a handle which can be used to unsubscribe """ sourcenode = Node(self.server, sourcenode) if evfilter is None: if not type(evtypes) in (list, tuple): evtypes = [evtypes] evtypes = [Node(self.server, evtype) for evtype in evtypes] evfilter = events.get_filter_from_event_type(evtypes) return self._subscribe(sourcenode, ua.AttributeIds.EventNotifier, evfilter, queuesize=queuesize)
def _instantiate_node(server, parentid, rdesc, nodeid, bname, recursive=True): """ instantiate a node type under parent """ addnode = ua.AddNodesItem() addnode.RequestedNewNodeId = nodeid addnode.BrowseName = bname addnode.ParentNodeId = parentid addnode.ReferenceTypeId = rdesc.ReferenceTypeId addnode.TypeDefinition = rdesc.TypeDefinition node_type = Node(server, rdesc.NodeId) if rdesc.NodeClass in (ua.NodeClass.Object, ua.NodeClass.ObjectType): addnode.NodeClass = ua.NodeClass.Object _read_and_copy_attrs(node_type, ua.ObjectAttributes(), addnode) elif rdesc.NodeClass in (ua.NodeClass.Variable, ua.NodeClass.VariableType): addnode.NodeClass = ua.NodeClass.Variable _read_and_copy_attrs(node_type, ua.VariableAttributes(), addnode) elif rdesc.NodeClass in (ua.NodeClass.Method,): addnode.NodeClass = ua.NodeClass.Method _read_and_copy_attrs(node_type, ua.MethodAttributes(), addnode) else: print("Instantiate: Node class not supported: ", rdesc.NodeClass) return res = server.add_nodes([addnode])[0] if recursive: descs = node_type.get_children_descriptions(includesubtypes=False) for c_rdesc in descs: _instantiate_node(server, res.AddedNodeId, c_rdesc, nodeid=ua.NodeId(namespaceidx=res.AddedNodeId.NamespaceIndex), bname=c_rdesc.BrowseName) return Node(server, res.AddedNodeId)
def createEditor(self, parent, option, idx): if idx.column() != 1: return None item = self.attrs_widget.model.itemFromIndex(idx) attr, dv = item.data(Qt.UserRole) text = item.text() if attr == ua.AttributeIds.NodeId: return None if dv.Value.VariantType == ua.VariantType.Boolean: combo = QComboBox(parent) combo.addItem("True") combo.addItem("False") combo.setCurrentText(text) return combo elif attr == ua.AttributeIds.NodeClass: combo = QComboBox(parent) for nclass in ua.NodeClass: combo.addItem(nclass.name) combo.setCurrentText(text) return combo elif attr == ua.AttributeIds.DataType: nodeid = getattr(ua.ObjectIds, text) node = Node(self.attrs_widget.current_node.server, nodeid) startnode = Node(self.attrs_widget.current_node.server, ua.ObjectIds.BaseDataType) button = GetNodeButton(parent, node, startnode) return button elif attr in (ua.AttributeIds.AccessLevel, ua.AttributeIds.UserAccessLevel, ua.AttributeIds.WriteMask, ua.AttributeIds.UserWriteMask, ua.AttributeIds.EventNotifier): #FIXME: make a ByteEditor we can choose and click bit ala QtCreator raise NotImplementedError else: return QStyledItemDelegate.createEditor(self, parent, option, idx)
def _get_node(self, nodeid): if isinstance(nodeid, ua.NodeId): node = Node(self.server, nodeid) elif isinstance(nodeid, Node): node = nodeid else: node = Node(self.server, ua.NodeId(nodeid)) return node
def start(self): self.logger.info("starting internal server") self.loop.start() Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_State)).set_value(0) Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_StartTime)).set_value( datetime.now()) self._set_current_time()
def _instantiate_node(server, parentid, rdesc, nodeid, bname, recursive=True): """ instantiate a node type under parent """ node_type = Node(server, rdesc.NodeId) refs = node_type.get_referenced_nodes(refs=ua.ObjectIds.HasModellingRule) # skip optional elements if len(refs) == 1 and refs[0].nodeid == ua.NodeId( ua.ObjectIds.ModellingRule_Optional): return [] addnode = ua.AddNodesItem() addnode.RequestedNewNodeId = nodeid addnode.BrowseName = bname addnode.ParentNodeId = parentid addnode.ReferenceTypeId = rdesc.ReferenceTypeId addnode.TypeDefinition = rdesc.TypeDefinition if rdesc.NodeClass in (ua.NodeClass.Object, ua.NodeClass.ObjectType): addnode.NodeClass = ua.NodeClass.Object _read_and_copy_attrs(node_type, ua.ObjectAttributes(), addnode) elif rdesc.NodeClass in (ua.NodeClass.Variable, ua.NodeClass.VariableType): addnode.NodeClass = ua.NodeClass.Variable _read_and_copy_attrs(node_type, ua.VariableAttributes(), addnode) elif rdesc.NodeClass in (ua.NodeClass.Method, ): addnode.NodeClass = ua.NodeClass.Method _read_and_copy_attrs(node_type, ua.MethodAttributes(), addnode) else: print("Instantiate: Node class not supported: ", rdesc.NodeClass) return res = server.add_nodes([addnode])[0] added_nodes = [res.AddedNodeId] if recursive: parents = ua_utils.get_node_supertypes(node_type, includeitself=True) node = Node(server, res.AddedNodeId) for parent in parents: descs = parent.get_children_descriptions(includesubtypes=False) for c_rdesc in descs: # skip items that already exists, prefer the 'lowest' one in object hierarchy if not ua_utils.is_child_present(node, c_rdesc.BrowseName): nodeids = _instantiate_node( server, res.AddedNodeId, c_rdesc, nodeid=ua.NodeId( namespaceidx=res.AddedNodeId.NamespaceIndex), bname=c_rdesc.BrowseName) added_nodes.extend(nodeids) return added_nodes
def _lsprint_1(node, depth, indent=""): if not indent: print("{:30} {:25} {:25} {:25}".format("DisplayName", "NodeId", "BrowseName", "Value")) print("") for desc in node.get_children_descriptions(): if desc.NodeClass == ua.NodeClass.Variable: val = Node(node.server, desc.NodeId).get_value() print("{}{:30} {!s:25} {!s:25}, {!s:3}".format(indent, desc.DisplayName.to_string(), desc.NodeId.to_string(), desc.BrowseName.to_string(), val)) else: print("{}{:30} {!s:25} {!s:25}".format(indent, desc.DisplayName.to_string(), desc.NodeId.to_string(), desc.BrowseName.to_string())) if depth: _lsprint_1(Node(node.server, desc.NodeId), depth - 1, indent + " ")
def start(self): self.logger.info("starting internal server") for edp in self.endpoints: self._known_servers[edp.Server.ApplicationUri] = ServerDesc( edp.Server) self.loop.start() Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_State)).set_value(0) Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_StartTime)).set_value( datetime.now()) if not self.disabled_clock: self._set_current_time()
def _instanciate_node(server, parentid, rdesc, idx): """ Instanciate a new node under 'parent' using a type """ print("Instanciating: node %s in %s" % (rdesc, parentid)) addnode = ua.AddNodesItem() addnode.RequestedNewNodeId = ua.generate_nodeid(idx) addnode.BrowseName = rdesc.BrowseName addnode.NodeClass = rdesc.NodeClass addnode.ParentNodeId = parentid addnode.ReferenceTypeId = ua.TwoByteNodeId(ua.ObjectIds.HasComponent) addnode.TypeDefinition = rdesc.TypeDefinition print("ADDNODE", addnode) node_type = Node(server, rdesc.NodeId) if rdesc.NodeClass in (ua.NodeClass.Object, ua.NodeClass.ObjectType): print(node_type, " is object") _read_and_copy_attrs(node_type, ua.ObjectAttributes(), addnode) #_add_object_attrs(addnode, rdesc, node_type) elif rdesc.NodeClass in (ua.NodeClass.Variable, ua.NodeClass.VariableType): print(node_type, " is variable") _read_and_copy_attrs(node_type, ua.VariableAttributes(), addnode) #_add_variable_attrs(addnode, rdesc, node_type) else: print("Node class not supported: ", rdesc.NodeClass) print("ADDNODE FINAL ", addnode) server.add_nodes([addnode]) refs = [] ref = ua.AddReferencesItem() ref.IsForward = True ref.ReferenceTypeId = addnode.ReferenceTypeId ref.SourceNodeId = parentid ref.TargetNodeClass = addnode.NodeClass ref.TargetNodeId = addnode.RequestedNewNodeId refs.append(ref) server.add_references(refs) descs = node_type.get_children_descriptions( includesubtypes=False) #FIXME: should be false print("node is", rdesc.NodeId, node_type, node_type.get_children()) print("Children are: ", descs) for rdesc in descs: _instanciate_node(server, addnode.RequestedNewNodeId, rdesc, idx) return Node(server, addnode.RequestedNewNodeId)
def __init__(self, server): self.root = Node(server, ObjectIds.RootFolder) self.objects = Node(server, ObjectIds.ObjectsFolder) self.server = Node(server, ObjectIds.Server) self.types = Node(server, ObjectIds.TypesFolder) self.base_object_type = Node(server, ObjectIds.BaseObjectType) self.base_data_type = Node(server, ObjectIds.BaseDataType) self.base_event_type = Node(server, ObjectIds.BaseEventType) self.base_variable_type = Node(server, ObjectIds.BaseVariableType) self.folder_type = Node(server, ObjectIds.FolderType)
def __init__(self, isession, etype=None, source=ua.ObjectIds.Server): if not etype: etype = ua.BaseEvent() self.logger = logging.getLogger(__name__) self.isession = isession self.event = None node = None if isinstance(etype, ua.BaseEvent): self.event = etype elif isinstance(etype, Node): node = etype elif isinstance(etype, ua.NodeId): node = Node(self.isession, etype) else: node = Node(self.isession, ua.NodeId(etype)) if node: self.event = get_event_from_type_node(node) if isinstance(source, Node): pass elif isinstance(source, ua.NodeId): source = Node(isession, source) else: source = Node(isession, ua.NodeId(source)) if self.event.SourceNode: if source.nodeid != self.event.SourceNode: self.logger.warning( "Source NodeId: '%s' and event SourceNode: '%s' are not the same. Using '%s' as SourceNode", str(source.nodeid), str(self.event.SourceNode), str(self.event.SourceNode)) source = Node(self.isession, self.event.SourceNode) self.event.SourceNode = source.nodeid self.event.SourceName = source.get_browse_name().Name source.set_attribute(ua.AttributeIds.EventNotifier, ua.DataValue(ua.Variant(1, ua.VariantType.Byte))) refs = [] ref = ua.AddReferencesItem() ref.IsForward = True ref.ReferenceTypeId = ua.NodeId(ua.ObjectIds.GeneratesEvent) ref.SourceNodeId = source.nodeid ref.TargetNodeClass = ua.NodeClass.ObjectType ref.TargetNodeId = self.event.EventType refs.append(ref) results = self.isession.add_references(refs)
def __init__(self, isession, etype=None, emitting_node=ua.ObjectIds.Server): if not etype: etype = event_objects.BaseEvent() self.logger = logging.getLogger(__name__) self.isession = isession self.event = None node = None if isinstance(etype, event_objects.BaseEvent): self.event = etype elif isinstance(etype, Node): node = etype elif isinstance(etype, ua.NodeId): node = Node(self.isession, etype) else: node = Node(self.isession, ua.NodeId(etype)) if node: self.event = events.get_event_obj_from_type_node(node) if isinstance(emitting_node, Node): pass elif isinstance(emitting_node, ua.NodeId): emitting_node = Node(isession, emitting_node) else: emitting_node = Node(isession, ua.NodeId(emitting_node)) self.event.emitting_node = emitting_node.nodeid if not self.event.SourceNode: self.event.SourceNode = emitting_node.nodeid self.event.SourceName = emitting_node.get_browse_name().Name emitting_node.set_event_notifier([ua.EventNotifier.SubscribeToEvents]) refs = [] ref = ua.AddReferencesItem() ref.IsForward = True ref.ReferenceTypeId = ua.NodeId(ua.ObjectIds.GeneratesEvent) ref.SourceNodeId = emitting_node.nodeid ref.TargetNodeClass = ua.NodeClass.ObjectType ref.TargetNodeId = self.event.EventType refs.append(ref) results = self.isession.add_references(refs) # result.StatusCode.check() self.emitting_node = emitting_node
def instantiate(parent, node_type, nodeid=None, bname=None, dname=None, idx=0): """ instantiate a node type under a parent node. nodeid and browse name of new node can be specified, or just namespace index If they exists children of the node type, such as components, variables and properties are also instantiated """ rdesc = _rdesc_from_node(parent, node_type) rdesc.TypeDefinition = node_type.nodeid if nodeid is None: nodeid = ua.NodeId( namespaceidx=idx ) # will trigger automatic node generation in namespace idx if bname is None: bname = rdesc.BrowseName elif isinstance(bname, str): bname = ua.QualifiedName.from_string(bname) nodeids = _instantiate_node(parent.server, parent.nodeid, rdesc, nodeid, bname, dname=dname) return [Node(parent.server, nid) for nid in nodeids]
def _save_structs(self): """ Save struct and delete our design nodes. They will need to be recreated """ struct_node = self.server_mgr.get_node(ua.ObjectIds.Structure) structs = [] to_delete = [] for node in self.new_nodes: # FIXME: we do not support inheritance parent = node.get_parent() if parent == struct_node: bname = node.get_browse_name() st = _Struct(bname.Name, "ExtensionObject") childs = node.get_children() for child in childs: bname = child.get_browse_name() try: dtype = child.get_data_type() except ua.UaError: logger.warning( "could not get data type for node %s, %s, skipping", child, child.get_browse_name()) continue dtype_name = Node(node.server, dtype).get_browse_name() st.fields.append([bname.Name, dtype_name.Name]) to_delete.append(child) structs.append(st) if structs: self._save_bsd(structs) for node in to_delete: node.delete() if node in self.new_nodes: self.new_nodes.remove(node)
def add_item(self, desc, parent=None, node=None): item = [QStandardItem(desc.DisplayName.to_string()), QStandardItem(desc.BrowseName.to_string()), QStandardItem(desc.NodeId.to_string())] if desc.NodeClass == ua.NodeClass.Object: if desc.TypeDefinition == ua.TwoByteNodeId(ua.ObjectIds.FolderType): item[0].setIcon(QIcon(":/folder.svg")) else: item[0].setIcon(QIcon(":/object.svg")) elif desc.NodeClass == ua.NodeClass.Variable: if desc.TypeDefinition == ua.TwoByteNodeId(ua.ObjectIds.PropertyType): item[0].setIcon(QIcon(":/property.svg")) else: item[0].setIcon(QIcon(":/variable.svg")) elif desc.NodeClass == ua.NodeClass.Method: item[0].setIcon(QIcon(":/method.svg")) elif desc.NodeClass == ua.NodeClass.ObjectType: item[0].setIcon(QIcon(":/object_type.svg")) elif desc.NodeClass == ua.NodeClass.VariableType: item[0].setIcon(QIcon(":/variable_type.svg")) elif desc.NodeClass == ua.NodeClass.DataType: item[0].setIcon(QIcon(":/data_type.svg")) elif desc.NodeClass == ua.NodeClass.ReferenceType: item[0].setIcon(QIcon(":/reference_type.svg")) if node: item[0].setData(node) else: parent_node = parent.data() item[0].setData(Node(parent_node.server, desc.NodeId)) if parent: return parent.appendRow(item) else: return self.appendRow(item)
def trigger(self, time_attr=None, message=None): """ Trigger the event. This will send a notification to all subscribed clients """ self.event.EventId = ua.Variant(uuid.uuid4().hex.encode('utf-8'), ua.VariantType.ByteString) if time_attr: self.event.Time = time_attr else: self.event.Time = datetime.utcnow() self.event.ReceiveTime = datetime.utcnow() self.event.LocalTime = ua.uaprotocol_auto.TimeZoneDataType() if sys.version_info.major > 2: localtime = time.localtime(self.event.Time.timestamp()) self.event.LocalTime.Offset = localtime.tm_gmtoff // 60 else: localtime = time.localtime(time.mktime( self.event.Time.timetuple())) self.event.LocalTime.Offset = -(time.altzone if localtime.tm_isdst else time.timezone) self.event.LocalTime.DaylightSavingInOffset = bool( localtime.tm_isdst != -1) if message: self.event.Message = ua.LocalizedText(message) elif not self.event.Message: self.event.Message = ua.LocalizedText( Node(self.isession, self.event.SourceNode).get_browse_name().Text) self.isession.subscription_service.trigger_event(self.event)
def create_monitored_items(self, monitored_items): """ low level method to have full control over subscription parameters Client handle must be unique since it will be used as key for internal registration of data """ params = ua.CreateMonitoredItemsParameters() params.SubscriptionId = self.subscription_id params.ItemsToCreate = monitored_items params.TimestampsToReturn = ua.TimestampsToReturn.Neither mids = [] results = self.server.create_monitored_items(params) # FIXME: Race condition here # We lock as early as possible. But in some situation, a notification may arrives before # locking and we will not be able to prosess it. To avoid issues, users should subscribe # to all nodes at once with self._lock: for idx, result in enumerate(results): mi = params.ItemsToCreate[idx] if not result.StatusCode.is_good(): mids.append(result.StatusCode) continue data = SubscriptionItemData() data.client_handle = mi.RequestedParameters.ClientHandle data.node = Node(self.server, mi.ItemToMonitor.NodeId) data.attribute = mi.ItemToMonitor.AttributeId data.server_handle = result.MonitoredItemId #data.mfilter = result.FilterResult data.mfilter = mi.RequestedParameters.Filter self._monitoreditems_map[mi.RequestedParameters.ClientHandle] = data mids.append(result.MonitoredItemId) return mids
def test_guid_node_id(self): """ Test that a Node can be instantiated with a GUID string and that the NodeId ca be converted to binary. """ node = Node(None, "ns=4;g=35d5f86f-2777-4550-9d48-b098f5ee285c") binary_node_id = ua.ua_binary.nodeid_to_binary(node.nodeid) assert type(binary_node_id) is bytes
def create_monitored_items(self, monitored_items): """ low level method to have full control over subscription parameters Client handle must be unique since it will be used as key for internal registration of data """ params = ua.CreateMonitoredItemsParameters() params.SubscriptionId = self.subscription_id params.ItemsToCreate = monitored_items params.TimestampsToReturn = ua.TimestampsToReturn.Both # insert monitored item into map to avoid notification arrive before result return # server_handle is left as None in purpose as we don't get it yet. with self._lock: for mi in monitored_items: data = SubscriptionItemData() data.client_handle = mi.RequestedParameters.ClientHandle data.node = Node(self.server, mi.ItemToMonitor.NodeId) data.attribute = mi.ItemToMonitor.AttributeId #TODO: Either use the filter from request or from response. Here it uses from request, in modify it uses from response data.mfilter = mi.RequestedParameters.Filter self._monitoreditems_map[mi.RequestedParameters.ClientHandle] = data results = self.server.create_monitored_items(params) mids = [] # process result, add server_handle, or remove it if failed with self._lock: for idx, result in enumerate(results): mi = params.ItemsToCreate[idx] if not result.StatusCode.is_good(): del self._monitoreditems_map[mi.RequestedParameters.ClientHandle] mids.append(result.StatusCode) continue data = self._monitoreditems_map[mi.RequestedParameters.ClientHandle] data.server_handle = result.MonitoredItemId mids.append(result.MonitoredItemId) return mids
def subscribe_events(self, sourcenode=ua.ObjectIds.Server, evtype=ua.ObjectIds.BaseEventType, evfilter=None): """ Subscribe to events from a node. Default node is Server node. In most servers the server node is the only one you can subscribe to. if evfilter is provided, evtype is ignored Return a handle which can be used to unsubscribe """ sourcenode = Node(self.server, sourcenode) if evfilter is None: evfilter = events.get_filter_from_event_type( Node(self.server, evtype)) return self._subscribe(sourcenode, ua.AttributeIds.EventNotifier, evfilter)
def get_node(self): text = self.lineEdit.text() if text and text not in ("None", "Null"): current = ua.NodeId.from_string(text) else: current = ua.NodeId() return Node(self.server, current)
def createEditor(self, parent, option, idx): if idx.column() != 1: return None item = self.attrs_widget.model.itemFromIndex(idx) data = item.data(Qt.UserRole) if not data.is_editable(): return None text = item.text() if isinstance(data, (ListData, MemberData)): return QStyledItemDelegate.createEditor(self, parent, option, idx) elif data.attr == ua.AttributeIds.NodeId: return None elif data.uatype == ua.VariantType.Boolean: combo = QComboBox(parent) combo.addItem("True") combo.addItem("False") combo.setCurrentText(text) return combo elif data.attr == ua.AttributeIds.NodeClass: combo = QComboBox(parent) for nclass in ua.NodeClass: combo.addItem(nclass.name) combo.setCurrentText(text) return combo elif data.attr == ua.AttributeIds.ValueRank: combo = QComboBox(parent) for rank in ua.ValueRank: combo.addItem(rank.name) combo.setCurrentText(text) return combo elif data.attr == ua.AttributeIds.DataType: #nodeid = getattr(ua.ObjectIds, text) nodeid = data.value node = Node(self.attrs_widget.current_node.server, nodeid) startnode = Node(self.attrs_widget.current_node.server, ua.ObjectIds.BaseDataType) button = GetNodeButton(parent, node, startnode) return button elif data.attr in (ua.AttributeIds.AccessLevel, ua.AttributeIds.UserAccessLevel, ua.AttributeIds.WriteMask, ua.AttributeIds.UserWriteMask, ua.AttributeIds.EventNotifier): return BitEditor(parent, data.attr, data.value) else: return QStyledItemDelegate.createEditor(self, parent, option, idx)
def createEditor(self, parent, option, idx): if idx.column() > 1: return None data_idx = idx.sibling(idx.row(), 0) item = self._widget.model.itemFromIndex(data_idx) ref = item.data(Qt.UserRole) if idx.column() == 1: node = Node(self._widget.node.server, ref.NodeId) startnode = Node(self._widget.node.server, ua.ObjectIds.RootFolder) button = GetNodeTextButton(parent, node, startnode) return button elif idx.column() == 0: node = Node(self._widget.node.server, ref.ReferenceTypeId) startnode = Node(self._widget.node.server, ua.ObjectIds.ReferenceTypesFolder) button = GetNodeTextButton(parent, node, startnode) return button
def _lsprint_0(node, depth, indent=""): if not indent: print("{:30} {:25}".format("DisplayName", "NodeId")) print("") for desc in node.get_children_descriptions(): print("{}{:30} {:25}".format(indent, desc.DisplayName.to_string(), desc.NodeId.to_string())) if depth: _lsprint_0(Node(node.server, desc.NodeId), depth - 1, indent + " ")
def _lsprint_1(node, depth, indent=""): if not indent: print("{0:30} {1:25} {2:25} {3:25}".format("DisplayName", "NodeId", "BrowseName", "Value")) print("") for desc in node.get_children_descriptions(): if desc.NodeClass == ua.NodeClass.Variable: try: val = Node(node.server, desc.NodeId).get_value() except UaStatusCodeError as err: val = "Bad (0x{0:x})".format(err.code) print("{0}{1:30} {2!s:25} {3!s:25}, {4!s:3}".format( indent, desc.DisplayName.to_string(), desc.NodeId.to_string(), desc.BrowseName.to_string(), val)) else: print("{0}{1:30} {2!s:25} {3!s:25}".format( indent, desc.DisplayName.to_string(), desc.NodeId.to_string(), desc.BrowseName.to_string())) if depth: _lsprint_1(Node(node.server, desc.NodeId), depth - 1, indent + " ")
def _save_structs(self): """ Save struct and delete our design nodes. They will need to be recreated """ struct_node = self.server_mgr.get_node(ua.ObjectIds.Structure) dict_name = "TypeDictionary" idx = 1 urn = self.server_mgr.get_namespace_array()[1] to_delete = [] have_structs = False to_add = [] for node in self.new_nodes: # FIXME: we do not support inheritance parent = node.get_parent() if parent == struct_node: if not have_structs: dict_builder = self._create_type_dict_node(idx, urn, dict_name) dict_node = self.server_mgr.get_node(dict_builder.dict_id) have_structs = True bname = node.get_browse_name() try: dict_node.get_child(f"{idx}:{bname.Name}") struct = dict_builder.create_data_type(bname.Name, node.nodeid, init=False) except ua.UaError: logger.warning("DataType %s has not been initialized, doing it", bname) struct = dict_builder.create_data_type(bname.Name, node.nodeid, init=True) childs = node.get_children() for child in childs: bname = child.get_browse_name() try: dtype = child.get_data_type() except ua.UaError: logger.warning("could not get data type for node %s, %s, skipping", child, child.get_browse_name()) continue array = False if isinstance(child.get_value(), list) or child.get_array_dimensions(): array = True dtype_name = Node(node.server, dtype).get_browse_name() struct.add_field(bname.Name, dtype_name.Name, is_array=array) to_delete.append(child) to_add.extend([self.server_mgr.get_node(nodeid) for nodeid in struct.node_ids]) if have_structs: dict_builder.set_dict_byte_string() self.new_nodes.extend(to_add) for node in to_delete: self.delete_node(node, False)
def __init__(self): self.logger = logging.getLogger(__name__) self.endpoints = [] self._channel_id_counter = 5 self.allow_remote_admin = True 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.aspace = AddressSpace() self.attribute_service = AttributeService(self.aspace) self.view_service = ViewService(self.aspace) self.method_service = MethodService(self.aspace) self.node_mgt_service = NodeManagementService(self.aspace) # import address space from code generated from xml standard_address_space.fill_address_space(self.node_mgt_service) # import address space from save db to disc #standard_address_space.fill_address_space_from_disk(self.aspace) # import address space directly from xml, this has preformance impact so disabled #importer = xmlimporter.XmlImporter(self.node_mgt_service) #importer.import_xml("/home/olivier/python-opcua/schemas/Opc.Ua.NodeSet2.xml") self.loop = utils.ThreadLoop() self.subscription_service = SubscriptionService(self.loop, self.aspace) # create a session to use on server side self.isession = InternalSession(self, self.aspace, self.subscription_service, "Internal", user=User.Admin) self.current_time_node = Node( self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_CurrentTime)) uries = ["http://opcfoundation.org/UA/"] ns_node = Node(self.isession, ua.NodeId(ua.ObjectIds.Server_NamespaceArray)) ns_node.set_value(uries)
def add_item(self, desc, parent=None, node=None): dname = bname = "No Value" if desc.DisplayName: dname = desc.DisplayName.to_string() if desc.BrowseName: bname = desc.BrowseName.to_string() nodeid = desc.NodeId.to_string() item = [ QStandardItem(dname), QStandardItem(bname), QStandardItem(nodeid) ] if desc.NodeClass == ua.NodeClass.Object: if desc.TypeDefinition == ua.TwoByteNodeId( ua.ObjectIds.FolderType): item[0].setIcon(QIcon("icons/folder.svg")) else: try: object_type = self.custom_objects[desc.NodeId] icon = get_icon(object_type) except KeyError: icon = "icons/object.svg" item[0].setIcon(QIcon(icon)) elif desc.NodeClass == ua.NodeClass.Variable: if desc.TypeDefinition == ua.TwoByteNodeId( ua.ObjectIds.PropertyType): item[0].setIcon(QIcon("icons/property.svg")) else: item[0].setIcon(QIcon("icons/variable.svg")) elif desc.NodeClass == ua.NodeClass.Method: item[0].setIcon(QIcon("icons/method.svg")) elif desc.NodeClass == ua.NodeClass.ObjectType: item[0].setIcon(QIcon("icons/objecttype.svg")) elif desc.NodeClass == ua.NodeClass.VariableType: item[0].setIcon(QIcon("icons/variabletype.svg")) elif desc.NodeClass == ua.NodeClass.DataType: item[0].setIcon(QIcon("icons/datatype.svg")) elif desc.NodeClass == ua.NodeClass.ReferenceType: item[0].setIcon(QIcon("icons/referencetype.svg")) if node: item[0].setData(node, Qt.UserRole) else: parent_node = parent.data(Qt.UserRole) item[0].setData(Node(parent_node.server, desc.NodeId), Qt.UserRole) if parent: return parent.appendRow(item) else: return self.appendRow(item)
def trigger(self, time=None, message=None): """ Trigger the event. This will send a notification to all subscribed clients """ self.event.EventId = ua.Variant(uuid.uuid4().hex, ua.VariantType.ByteString) if time: self.event.Time = time else: self.event.Time = datetime.utcnow() self.event.ReceiveTime = datetime.utcnow() #FIXME: LocalTime is wrong but currently know better. For description s. Part 5 page 18 self.event.LocalTime = datetime.utcnow() if message: self.event.Message = ua.LocalizedText(message) elif not self.event.Message: self.event.Message = ua.LocalizedText(Node(self.isession, self.event.SourceNode).get_browse_name().Text) self.isession.subscription_service.trigger_event(self.event)