def _create_monitored_item(self, params): with self._lock: result = ua.MonitoredItemCreateResult() result.RevisedSamplingInterval = self.isub.data.RevisedPublishingInterval result.RevisedQueueSize = params.RequestedParameters.QueueSize result.FilterResult = ua.downcast_extobject(params.RequestedParameters.Filter) self._monitored_item_counter += 1 result.MonitoredItemId = self._monitored_item_counter self.logger.debug("Creating MonitoredItem with id %s", result.MonitoredItemId) mdata = MonitoredItemData() mdata.parameters = result mdata.mode = params.MonitoringMode mdata.client_handle = params.RequestedParameters.ClientHandle mdata.monitored_item_id = result.MonitoredItemId self._monitored_items[result.MonitoredItemId] = mdata if params.ItemToMonitor.AttributeId == ua.AttributeIds.EventNotifier: self.logger.info("request to subscribe to events for node %s and attribute %s", params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) self._monitored_events[params.ItemToMonitor.NodeId] = result.MonitoredItemId else: self.logger.info("request to subscribe to datachange for node %s and attribute %s", params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) result.StatusCode, handle = self.aspace.add_datachange_callback(params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId, self.datachange_callback) self.logger.debug("adding callback return status %s and handle %s", result.StatusCode, handle) mdata.callback_handle = handle self._monitored_datachange[handle] = result.MonitoredItemId # force data change event generation self.trigger_datachange(handle, params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) return result
def _create_monitored_item(self, params): with self._lock: result = ua.MonitoredItemCreateResult() result.RevisedSamplingInterval = self.data.RevisedPublishingInterval result.RevisedQueueSize = params.RequestedParameters.QueueSize #FIXME check and use value result.FilterResult = ua.downcast_extobject(params.RequestedParameters.Filter) self._monitored_item_counter += 1 result.MonitoredItemId = self._monitored_item_counter self.logger.debug("Creating MonitoredItem with id %s", result.MonitoredItemId) mdata = MonitoredItemData() mdata.parameters = result mdata.mode = params.MonitoringMode mdata.client_handle = params.RequestedParameters.ClientHandle mdata.monitored_item_id = result.MonitoredItemId self._monitored_items[result.MonitoredItemId] = mdata if params.ItemToMonitor.AttributeId == ua.AttributeIds.EventNotifier: self.logger.info("request to subscribe to events for node %s and attribute %s", params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) self._monitored_events[params.ItemToMonitor.NodeId] = result.MonitoredItemId else: self.logger.info("request to subscribe to datachange for node %s and attribute %s", params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) result.StatusCode, handle = self.aspace.add_datachange_callback(params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId, self.datachange_callback) self.logger.debug("adding callback return status %s and handle %s", result.StatusCode, handle) mdata.callback_handle = handle self._monitored_datachange[handle] = result.MonitoredItemId #force data change event generation self.trigger_datachange(handle, params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId) return result
def _add_nodeattributes(self, item, nodedata): item = ua.downcast_extobject(item) self._add_node_attr(item, nodedata, "AccessLevel", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "ArrayDimensions", ua.VariantType.Int32) self._add_node_attr(item, nodedata, "BrowseName", ua.VariantType.QualifiedName) self._add_node_attr(item, nodedata, "ContainsNoLoops", ua.VariantType.Boolean) self._add_node_attr(item, nodedata, "DataType", ua.VariantType.NodeId) self._add_node_attr(item, nodedata, "Description", ua.VariantType.LocalizedText) self._add_node_attr(item, nodedata, "DisplayName", ua.VariantType.LocalizedText) self._add_node_attr(item, nodedata, "EventNotifier", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "Executable", ua.VariantType.Boolean) self._add_node_attr(item, nodedata, "Historizing", ua.VariantType.Boolean) self._add_node_attr(item, nodedata, "InverseName", ua.VariantType.LocalizedText) self._add_node_attr(item, nodedata, "IsAbstract", ua.VariantType.Boolean) self._add_node_attr(item, nodedata, "MinimumSamplingInterval", ua.VariantType.Double) self._add_node_attr(item, nodedata, "NodeClass", ua.VariantType.UInt32) self._add_node_attr(item, nodedata, "NodeId", ua.VariantType.NodeId) self._add_node_attr(item, nodedata, "Symmetric", ua.VariantType.Boolean) self._add_node_attr(item, nodedata, "UserAccessLevel", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "UserExecutable", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "UserWriteMask", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "ValueRank", ua.VariantType.Int32) self._add_node_attr(item, nodedata, "WriteMask", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "UserWriteMask", ua.VariantType.Byte) self._add_node_attr(item, nodedata, "Value")
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 = ua.downcast_extobject(result.FilterResult) self._monitoreditems_map[mi.RequestedParameters.ClientHandle] = data mids.append(result.MonitoredItemId) return mids
def _modify_monitored_item(self, params): with self._lock: for mdata in self._monitored_items.values(): result = ua.MonitoredItemCreateResult() if mdata.monitored_item_id == params.MonitoredItemId: result.RevisedSamplingInterval = self.isub.data.RevisedPublishingInterval result.RevisedQueueSize = ua.downcast_extobject(params.RequestedParameters.QueueSize) result.FilterResult = params.RequestedParameters.Filter mdata.parameters = result return result # FIXME modify event subscriptions result = ua.MonitoredItemCreateResult() result.StatusCode(ua.StatusCodes.BadMonitoredItemIdInvalid) return result
def activate_session(self, params): self.logger.info("activate session") result = ua.ActivateSessionResult() if not self.state == SessionState.Created: raise utils.ServiceError(ua.StatusCodes.BadSessionIdInvalid) result.ServerNonce = self.nonce for _ in params.ClientSoftwareCertificates: result.Results.append(ua.StatusCode()) self.state = SessionState.Activated id_token = ua.downcast_extobject(params.UserIdentityToken) if id_token.TypeId == ua.FourByteNodeId(ua.ObjectIds.UserNameIdentityToken_Encoding_DefaultBinary): if self.iserver.allow_remote_admin and id_token.UserName in ("admin", "Admin"): self.user = User.Admin return result
def activate_session(self, params): self.logger.info("activate session") result = ua.ActivateSessionResult() if not self.state == SessionState.Created: raise utils.ServiceError(ua.StatusCodes.BadSessionIdInvalid) result.ServerNonce = self.nonce for _ in params.ClientSoftwareCertificates: result.Results.append(ua.StatusCode()) self.state = SessionState.Activated id_token = ua.downcast_extobject(params.UserIdentityToken) if id_token.TypeId == ua.FourByteNodeId( ua.ObjectIds.UserNameIdentityToken_Encoding_DefaultBinary): if self.iserver.allow_remote_admin and id_token.UserName in ( "admin", "Admin"): self.user = User.Admin return result
def _add_nodeattributes(self, item, nodedata): item = ua.downcast_extobject(item) if item.SpecifiedAttributes & ua.NodeAttributesMask.AccessLevel: nodedata.attributes[ua.AttributeIds.AccessLevel] = AttributeValue(ua.DataValue(ua.Variant(item.AccessLevel, ua.VariantType.Byte))) if item.SpecifiedAttributes & ua.NodeAttributesMask.ArrayDimensions: nodedata.attributes[ua.AttributeIds.ArrayDimensions] = AttributeValue(ua.DataValue(ua.Variant(item.ArrayDimensions, ua.VariantType.Int32))) if item.SpecifiedAttributes & ua.NodeAttributesMask.BrowseName: nodedata.attributes[ua.AttributeIds.BrowseName] = AttributeValue(ua.DataValue(ua.Variant(item.BrowseName, ua.VariantType.QualifiedName))) if item.SpecifiedAttributes & ua.NodeAttributesMask.ContainsNoLoops: nodedata.attributes[ua.AttributeIds.ContainsNoLoops] = AttributeValue(ua.DataValue(ua.Variant(item.ContainsNoLoops, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.DataType: nodedata.attributes[ua.AttributeIds.DataType] = AttributeValue(ua.DataValue(ua.Variant(item.DataType, ua.VariantType.NodeId))) if item.SpecifiedAttributes & ua.NodeAttributesMask.Description: nodedata.attributes[ua.AttributeIds.Description] = AttributeValue(ua.DataValue(ua.Variant(item.Description, ua.VariantType.LocalizedText))) if item.SpecifiedAttributes & ua.NodeAttributesMask.DisplayName: nodedata.attributes[ua.AttributeIds.DisplayName] = AttributeValue(ua.DataValue(ua.Variant(item.DisplayName, ua.VariantType.LocalizedText))) if item.SpecifiedAttributes & ua.NodeAttributesMask.EventNotifier: nodedata.attributes[ua.AttributeIds.EventNotifier] = AttributeValue(ua.DataValue(ua.Variant(item.EventNotifier, ua.VariantType.Byte))) if item.SpecifiedAttributes & ua.NodeAttributesMask.Executable: nodedata.attributes[ua.AttributeIds.Executable] = AttributeValue(ua.DataValue(ua.Variant(item.Executable, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.Historizing: nodedata.attributes[ua.AttributeIds.Historizing] = AttributeValue(ua.DataValue(ua.Variant(item.Historizing, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.InverseName: nodedata.attributes[ua.AttributeIds.InverseName] = AttributeValue(ua.DataValue(ua.Variant(item.InverseName, ua.VariantType.LocalizedText))) if item.SpecifiedAttributes & ua.NodeAttributesMask.IsAbstract: nodedata.attributes[ua.AttributeIds.IsAbstract] = AttributeValue(ua.DataValue(ua.Variant(item.IsAbstract, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.MinimumSamplingInterval: nodedata.attributes[ua.AttributeIds.MinimumSamplingInterval] = AttributeValue(ua.DataValue(ua.Variant(item.MinimumSamplingInterval, ua.VariantType.Double))) if item.SpecifiedAttributes & ua.NodeAttributesMask.NodeClass: nodedata.attributes[ua.AttributeIds.NodeClass] = AttributeValue(ua.DataValue(ua.Variant(item.NodeClass, ua.VariantType.UInt32))) if item.SpecifiedAttributes & ua.NodeAttributesMask.NodeId: nodedata.attributes[ua.AttributeIds.NodeId] = AttributeValue(ua.DataValue(ua.Variant(item.NodeId, ua.VariantType.NodeId))) if item.SpecifiedAttributes & ua.NodeAttributesMask.Symmetric: nodedata.attributes[ua.AttributeIds.Symmetric] = AttributeValue(ua.DataValue(ua.Variant(item.Symmetric, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.UserAccessLevel: nodedata.attributes[ua.AttributeIds.UserAccessLevel] = AttributeValue(ua.DataValue(ua.Variant(item.UserAccessLevel, ua.VariantType.Byte))) if item.SpecifiedAttributes & ua.NodeAttributesMask.UserExecutable: nodedata.attributes[ua.AttributeIds.UserExecutable] = AttributeValue(ua.DataValue(ua.Variant(item.UserExecutable, ua.VariantType.Boolean))) if item.SpecifiedAttributes & ua.NodeAttributesMask.UserWriteMask: nodedata.attributes[ua.AttributeIds.UserWriteMask] = AttributeValue(ua.DataValue(ua.Variant(item.UserWriteMask, ua.VariantType.Byte))) if item.SpecifiedAttributes & ua.NodeAttributesMask.ValueRank: nodedata.attributes[ua.AttributeIds.ValueRank] = AttributeValue(ua.DataValue(ua.Variant(item.ValueRank, ua.VariantType.Int32))) if item.SpecifiedAttributes & ua.NodeAttributesMask.WriteMask: nodedata.attributes[ua.AttributeIds.WriteMask] = AttributeValue(ua.DataValue(ua.Variant(item.WriteMask, ua.VariantType.Byte))) if item.SpecifiedAttributes & ua.NodeAttributesMask.Value: nodedata.attributes[ua.AttributeIds.Value] = AttributeValue(ua.DataValue(item.Value))
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 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) with self._lock: self._monitoreditems_map[mparams.ClientHandle] = data return result.MonitoredItemId
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