async def read_node_attribute(self, nodeId, attribute): """ Read node attribute based on given arguments. Giving correct dataType for value and node speeds up the write operation. Arguments Example nodeId: Target nodeId "ns=2;i=2" attribute: Target attribute of node "Value" Results OPCUAVar: OPC UA variable object <object> readTime: Time taken for read (ns) 12345678 """ rv = ua.ReadValueId() if nodeId == "": rv.NodeId = ua.NodeId.from_string(server.rootNodeId) else: rv.NodeId = ua.NodeId.from_string(nodeId) rv.AttributeId = ua.AttributeIds[attribute] params = ua.ReadParameters() params.NodesToRead.append(rv) result, readTime = await self.read(params) if attribute == "Value": return result[0], readTime else: return result[0]
def get_attributes(self, nodes, attr): self.logger.info("get_attribute") request = ua.ReadRequest() for node in nodes: rv = ua.ReadValueId() rv.NodeId = node rv.AttributeId = attr request.Parameters.NodesToRead.append(rv) data = self._uasocket.send_request(request) response = struct_from_binary(ua.ReadResponse, data) response.ResponseHeader.ServiceResult.check() return response.Results
def create_monitored_items(sub, dirty_nodes, attr): mirs = [] for dirty_node in dirty_nodes: try: node_var = Node(sub.server, NodeId().from_string(dirty_node["node"])) rv = ua.ReadValueId() rv.NodeId = node_var.nodeid rv.AttributeId = attr # rv.IndexRange //We leave it null, then the entire array is returned mparams = ua.MonitoringParameters() with sub._lock: sub._client_handle += 1 mparams.ClientHandle = sub._client_handle mparams.SamplingInterval = dirty_node["samplingInterval"] mparams.QueueSize = dirty_node["queueSize"] mparams.DiscardOldest = dirty_node["queueDiscardOldest"] == "True" if dirty_node["filter"] != "None": try: mfilter = DataChangeFilter() #DataChangeTrigger(0) = Status, DataChangeTrigger(1) = StatusValue, DataChangeTrigger(2) = StatusValueTimestamp mfilter.Trigger = DataChangeTrigger[dirty_node["filter"]["Trigger"]] # DeadbandType(0) = None, DeadbandType(1) = Absolute, DeadbandType(2) = Percent mfilter.DeadbandType = DeadbandType[dirty_node["filter"]["DeadbandType"]] mfilter.DeadbandValue = dirty_node["filter"]["DeadbandValue"] except: mfilter = None print(f"\n\nWARNING: Can't apply filter on node {dirty_node['node']}") else: mfilter = None if mfilter: mparams.Filter = mfilter mir = ua.MonitoredItemCreateRequest() mir.ItemToMonitor = rv mir.MonitoringMode = ua.MonitoringMode.Disabled if dirty_node["monitoringMode"] == "Disabled" else ua.MonitoringMode.Sampling if dirty_node["monitoringMode"] == "Sampling" else ua.MonitoringMode.Reporting mir.RequestedParameters = mparams mirs.append(mir) except: print("\nUnable to create monitored item for node {dirty_node['node']}") mids, results = sub_monitored_items_creation(sub, mirs) for i, r in enumerate(results): if dirty_node["samplingInterval"] != r.RevisedSamplingInterval or dirty_node["queueSize"] != r.RevisedQueueSize: print(f"\nServer has changed monitored item properties for node {dirty_node['node']}") print(f"Monitored item id: {r.MonitoredItemId}") print(f"Revised SamplingInterval: {r.RevisedSamplingInterval}") print(f"Revised QueueSize: {r.RevisedQueueSize}") print(f"Filter Result: {r.FilterResult}\n") return mids
def get_attribute(self, attr): """ Read one attribute of a node result code from server is checked and an exception is raised in case of error """ rv = ua.ReadValueId() rv.NodeId = self.nodeid rv.AttributeId = attr params = ua.ReadParameters() params.NodesToRead.append(rv) result = self.server.read(params) result[0].StatusCode.check() return result[0]
def get_attributes(self, attrs): """ Read several attributes of a node list of DataValue is returned """ params = ua.ReadParameters() for attr in attrs: rv = ua.ReadValueId() rv.NodeId = self.nodeid rv.AttributeId = attr params.NodesToRead.append(rv) results = self.server.read(params) return results
async def batch_load_fn(self, attributeKeys): """ Iterates through the attributeKeys and retrieves data from OPC UA servers based on the attributeKey values. Arguments attributeKeys: List of strings with required infromation to retrieve the attributes from OPC UA servers. Template: "Server/NodeId/Attribute" Example: "TestServer/ns=2;i=2/Value" Results sortedResults: List of values returned by the OPC UA server for each attribute. Also includes OPC UA read time with each attribute. In same order as attributeKeys. Example: [<opcua_object>, readTime] """ servers = defaultdict(list) i = 0 for attribute in attributeKeys: info = attribute.split("/") servers[info[0]].append([i, info[1], info[2]]) i += 1 sortedResults = [None] * len(attributeKeys) for serverName, attributes in servers.items(): params = ua.ReadParameters() server = getServer(serverName) for info in attributes: rv = ua.ReadValueId() if info[1] == "": rv.NodeId = ua.NodeId.from_string(server.rootNodeId) else: rv.NodeId = ua.NodeId.from_string(info[1]) rv.AttributeId = ua.AttributeIds[info[2]] params.NodesToRead.append(rv) results, readTime = await server.read(params) i = 0 for info in attributes: sortedResults[info[0]] = [results[i], readTime] i += 1 return sortedResults
def make_monitored_item_request(self, subscription, node, attr, sampling_interval, client_handle, filter, queuesize, discard_oldest): rv = ua.ReadValueId() rv.NodeId = node.nodeid rv.AttributeId = attr mparams = ua.MonitoringParameters() with subscription._lock: subscription._client_handle = client_handle mparams.ClientHandle = subscription._client_handle mparams.SamplingInterval = sampling_interval mparams.QueueSize = queuesize mparams.DiscardOldest = discard_oldest if filter: mparams.Filter = filter mir = ua.MonitoredItemCreateRequest() #stack request mir.ItemToMonitor = rv mir.MonitoringMode = ua.MonitoringMode.Reporting mir.RequestedParameters = mparams return mir
def _make_monitored_item_request(self, node, attr, mfilter, queuesize): rv = ua.ReadValueId() rv.NodeId = node.nodeid rv.AttributeId = attr # rv.IndexRange //We leave it null, then the entire array is returned mparams = ua.MonitoringParameters() with self._lock: self._client_handle += 1 mparams.ClientHandle = self._client_handle mparams.SamplingInterval = self.parameters.RequestedPublishingInterval mparams.QueueSize = queuesize mparams.DiscardOldest = True if mfilter: mparams.Filter = mfilter mir = ua.MonitoredItemCreateRequest() mir.ItemToMonitor = rv mir.MonitoringMode = ua.MonitoringMode.Reporting mir.RequestedParameters = mparams return mir
async def get_variable_nodes(self, node, nodeClass=2, variableList=None, depth=0, maxDepth=10): """ Eats a list of node object(s). Recursively finds nodes under given nodes that have given nodeClass. Returns node objects in a list. """ if variableList is None: variableList = [] depth += 1 if depth >= maxDepth: return variableList nodes = node.get_children() params = ua.ReadParameters() for node in nodes: rv = ua.ReadValueId() rv.NodeId = node.nodeid rv.AttributeId = ua.AttributeIds.NodeClass params.NodesToRead.append(rv) results = [] if len(params.NodesToRead) > 0: results, readTime = await self.read(params) for i in range(len(results)): if nodeClass == results[i].Value.Value: variableList.append(nodes[i]) await self.get_variable_nodes(node=nodes[i], nodeClass=nodeClass, variableList=variableList, depth=depth) return variableList
def _subscribe(self, node, attr, mfilter=None, queuesize=0): rv = ua.ReadValueId() rv.NodeId = node.nodeid rv.AttributeId = attr # rv.IndexRange //We leave it null, then the entire array is returned mparams = ua.MonitoringParameters() self._client_handle += 1 mparams.ClientHandle = self._client_handle mparams.SamplingInterval = self.parameters.RequestedPublishingInterval mparams.QueueSize = queuesize mparams.DiscardOldest = True if mfilter: mparams.Filter = mfilter mir = ua.MonitoredItemCreateRequest() mir.ItemToMonitor = rv mir.MonitoringMode = ua.MonitoringMode.Reporting mir.RequestedParameters = mparams params = ua.CreateMonitoredItemsParameters() params.SubscriptionId = self.subscription_id params.ItemsToCreate.append(mir) params.TimestampsToReturn = ua.TimestampsToReturn.Neither with self._lock: results = self.server.create_monitored_items(params) result = results[0] result.StatusCode.check() data = SubscriptionItemData() data.client_handle = mparams.ClientHandle data.node = node data.attribute = attr data.server_handle = result.MonitoredItemId data.mfilter = ua.downcast_extobject(result.FilterResult) self._monitoreditems_map[mparams.ClientHandle] = data return result.MonitoredItemId
def add(self, attr): rv = ua.ReadValueId() rv.NodeId = self.nodeid rv.AttributeId = attr self.params.NodesToRead.append(rv) self._debug_attr.append(attr)
def create_monitored_items(self, nodes, index): monitored_items = [] if not isinstance(nodes, list): nodes = [nodes] for node in nodes: # Set item to monitor rv = ua.ReadValueId() rv.NodeId = node.nodeid rv.AttributeId = ua.AttributeIds.Value # Set monitoring parameters mparams = ua.MonitoringParameters() self._client_handle += 1 mparams.ClientHandle = self._client_handle mparams.SamplingInterval = self.samplingInterval mparams.QueueSize = self.queueSize mparams.DiscardOldest = self.discardOldest # Create monitored item filter if self.dataChangeFilter: mfilter = ua.DataChangeFilter() mfilter.Trigger = ua.DataChangeTrigger(self.dataChangeTrigger) if self.deadbandType == ua.DeadbandType.Absolute: if node.get_data_value( ).Value.VariantType in self.numericTypes: mfilter.DeadbandType = self.deadbandType mfilter.DeadbandValue = self.deadbandValue # absolute float value or from 0 to 100 for percentage deadband else: self.deadbandType = ua.DeadbandType.None_ mfilter.DeadbandType = self.deadbandType elif self.deadbandType == ua.DeadbandType.Percent: has_EURange = False if node.get_type_definition( ).Identifier == ua.object_ids.ObjectIds.AnalogItemType: # Get node properties descriptions = node.get_references( ua.ObjectIds.HasProperty, ua.BrowseDirection.Forward, ua.NodeClass.Variable, False) for desc in descriptions: if desc.BrowseName.Name == "EURange" and self.get_node( desc.NodeId).get_value() is not None: has_EURange = True if has_EURange: mfilter.DeadbandType = self.deadbandType mfilter.DeadbandValue = self.deadbandValue # absolute float value or from 0 to 100 for percentage deadband else: self.deadbandType = ua.DeadbandType.None_ mfilter.DeadbandType = self.deadbandType else: mfilter = None mparams.Filter = mfilter # Create monitored item request mir = ua.MonitoredItemCreateRequest() mir.ItemToMonitor = rv mir.MonitoringMode = ua.MonitoringMode.Reporting mir.RequestedParameters = mparams # Append to list monitored_items.append(mir) sub, monitored_items_handles = self._datachange_subs[index] handles = sub.create_monitored_items(monitored_items) for i in range(len(handles)): handle = handles[i] if type(handle) == ua.StatusCode: handle.check() monitored_items_handles[nodes[i].nodeid] = handle