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 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(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