def set_attribute_value(self, nodeid, attr, value): with self._lock: self.logger.debug("set attr val: %s %s %s", nodeid, attr, value) node = self._nodes.get(nodeid, None) if node is None: return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) attval = node.attributes.get(attr, None) if attval is None: self.logger.warning( "Tried to write attribute '%s' in %s, but the attribute is missing", attr, nodeid) return ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid) old = attval.value attval.value = value cbs = [] if old.Value != value.Value: # only send call callback when a value change has happend cbs = list(attval.datachange_callbacks.items()) for k, v in cbs: try: v(k, value) except Exception as ex: self.logger.exception( "Error calling datachange callback %s, %s, %s", k, v, ex) return ua.StatusCode()
def _call(self, method): res = ua.CallMethodResult() if method.ObjectId not in self._aspace or method.MethodId not in self._aspace: res.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdInvalid) else: node = self._aspace[method.MethodId] if node.call is None: res.StatusCode = ua.StatusCode(ua.StatusCodes.BadNothingToDo) else: try: result = node.call(method.ObjectId, *method.InputArguments) if isinstance(result, ua.CallMethodResult): res = result elif isinstance(result, ua.StatusCode): res.StatusCode = result else: res.OutputArguments = result while len(res.InputArgumentResults) < len( method.InputArguments): res.InputArgumentResults.append(ua.StatusCode()) except Exception: self.logger.exception( "Error executing method call %s, an exception was raised: ", method) res.StatusCode = ua.StatusCode( ua.StatusCodes.BadUnexpectedError) return res
def write(self, params, user=User.Admin): self.logger.debug("write %s as user %s", params, user) res = [] for writevalue in params.NodesToWrite: if user != User.Admin: if writevalue.AttributeId != ua.AttributeIds.Value: res.append( ua.StatusCode(ua.StatusCodes.BadUserAccessDenied)) continue al = self._aspace.get_attribute_value( writevalue.NodeId, ua.AttributeIds.AccessLevel) ual = self._aspace.get_attribute_value( writevalue.NodeId, ua.AttributeIds.UserAccessLevel) if not ua.ua_binary.test_bit( al.Value.Value, ua.AccessLevel. CurrentWrite) or not ua.ua_binary.test_bit( ual.Value.Value, ua.AccessLevel.CurrentWrite): res.append( ua.StatusCode(ua.StatusCodes.BadUserAccessDenied)) continue res.append( self._aspace.set_attribute_value(writevalue.NodeId, writevalue.AttributeId, writevalue.Value)) return res
def test_string_to_variant_status_code(self): s_statuscode = "Good" statuscode = ua.StatusCode(ua.StatusCodes.Good) s_statuscode2 = "Uncertain" statuscode2 = ua.StatusCode(ua.StatusCodes.Uncertain) self.assertEqual(string_to_val(s_statuscode, ua.VariantType.StatusCode), statuscode) self.assertEqual(string_to_val(s_statuscode2, ua.VariantType.StatusCode), statuscode2)
def set_attribute_value(self, nodeid, attr, value): with self._lock: self.logger.debug("set attr val: %s %s %s", nodeid, attr, value) if nodeid not in self._nodes: return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) node = self._nodes[nodeid] if attr not in node.attributes: return ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid) if not value.SourceTimestamp: value.SourceTimestamp = datetime.utcnow() if not value.ServerTimestamp: value.ServerTimestamp = datetime.utcnow() attval = node.attributes[attr] old = attval.value attval.value = value cbs = [] if old.Value != value.Value: # only send call callback when a value change has happend cbs = list(attval.datachange_callbacks.items()) for k, v in cbs: try: v(k, value) except Exception as ex: self.logger.exception("Error calling datachange callback %s, %s, %s", k, v, ex) return ua.StatusCode()
def set_attribute_value(self, nodeid, attr, value): with self._lock: self.logger.debug("set attr val: %s %s %s", nodeid, attr, value) if not nodeid in self._nodes: return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) node = self._nodes[nodeid] if not attr in node.attributes: return ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid) if not value.SourceTimestamp: value.SourceTimestamp = datetime.now() if not value.ServerTimestamp: value.ServerTimestamp = datetime.now() attval = node.attributes[attr] attval.value = value if attval.value_callback: return attval.value_callback(nodeid, attr, value) for k, v in attval.datachange_callbacks.items(): try: v(k, value) except Exception as ex: self.logger.exception( "Error calling datachange callback %s, %s, %s", k, v, ex) return ua.StatusCode()
def _delete_node(self, item, user): if not user == User.Admin: return ua.StatusCode(ua.StatusCodes.BadUserAccessDenied) if item.NodeId not in self._aspace: self.logger.warning("DeleteNodesItem: node does not exists") return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) if item.DeleteTargetReferences: for elem in self._aspace.keys(): for rdesc in self._aspace[elem].references: if rdesc.NodeId == item.NodeId: self._aspace[elem].references.remove(rdesc) for handle, callback in list(self._aspace[item.NodeId].attributes[ ua.AttributeIds.Value].datachange_callbacks.items()): try: callback(handle, None, ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown)) self._aspace.delete_datachange_callback(handle) except Exception as ex: self.logger.exception( "Error calling datachange callback %s, %s, %s", k, v, ex) del self._aspace[item.NodeId] return ua.StatusCode()
def turn_pump_off(parent): if manualoperation.get_value() == True: pump_closed.set_value(True) pump_q.set_value(0) return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def turn_pump_on(parent): if manualoperation.get_value() == True: pump_closed.set_value(False) pump_q.set_value(1) # Flowrate defined in project implementation return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def turn_control_on(parent): if manualoperation.get_value() == True: c_sp1_open.set_value(True) c_sp2_open.set_value(True) c_sp3_open.set_value(True) return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def turn_fuzzy_off(parent): if manualoperation.get_value() == True: f_sp1_open.set_value(False) f_sp2_open.set_value(False) f_sp3_open.set_value(False) return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def _add_reference(self, addref, user): sourcedata = self._aspace.get(addref.SourceNodeId) if sourcedata is None: return ua.StatusCode(ua.StatusCodes.BadSourceNodeIdInvalid) if addref.TargetNodeId not in self._aspace: return ua.StatusCode(ua.StatusCodes.BadTargetNodeIdInvalid) if user != User.Admin: return ua.StatusCode(ua.StatusCodes.BadUserAccessDenied) return self._add_reference_no_check(sourcedata, addref)
def func2(parent, methodname, value): if methodname == "panic": return ua.StatusCode(ua.StatusCodes.BadOutOfMemory) if methodname != "sin": res = ua.CallMethodResult() res.StatusCode = ua.StatusCode(ua.StatusCodes.BadInvalidArgument) res.InputArgumentResults = [ua.StatusCode(ua.StatusCodes.BadNotSupported), ua.StatusCode()] return res return math.sin(value)
def _add_node(self, item, user): result = ua.AddNodesResult() # If Identifier of requested NodeId is null we generate a new NodeId using # the namespace of the nodeid, this is an extention of the spec to allow # to requests the server to generate a new nodeid in a specified namespace if item.RequestedNewNodeId.has_null_identifier(): self.logger.debug( "RequestedNewNodeId has null identifier, generating Identifier" ) nodedata = NodeData( self._aspace.generate_nodeid( item.RequestedNewNodeId.NamespaceIndex)) else: nodedata = NodeData(item.RequestedNewNodeId) if nodedata.nodeid in self._aspace: self.logger.warning( "AddNodesItem: Requested NodeId %s already exists", nodedata.nodeid) result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists) return result if item.ParentNodeId.is_null(): # self.logger.warning("add_node: creating node %s without parent", nodedata.nodeid) # should return Error here, but the standard namespace define many nodes without parents... pass elif item.ParentNodeId not in self._aspace: self.logger.warning( "add_node: while adding node %s, requested parent node %s does not exists", nodedata.nodeid, item.ParentNodeId) result.StatusCode = ua.StatusCode( ua.StatusCodes.BadParentNodeIdInvalid) return result if not user == User.Admin: result.StatusCode = ua.StatusCode( ua.StatusCodes.BadUserAccessDenied) return result self._add_node_attributes(nodedata, item) # now add our node to db self._aspace[nodedata.nodeid] = nodedata if not item.ParentNodeId.is_null(): self._add_ref_from_parent(nodedata, item) self._add_ref_to_parent(nodedata, item, user) # add type definition if item.TypeDefinition != ua.NodeId(): self._add_type_definition(nodedata, item, user) result.StatusCode = ua.StatusCode() result.AddedNodeId = nodedata.nodeid return result
def toggle_manual(parent): if manualoperation.get_value() == True: manualoperation.set_value(False) return ua.StatusCode(0) elif manualoperation.get_value() == False: manualoperation.set_value(True) return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def _add_unique_reference(self, nodedata, desc): for r in nodedata.references: if r.ReferenceTypeId == desc.ReferenceTypeId and r.NodeId == desc.NodeId: if r.IsForward != desc.IsForward: self.logger.error("Cannot add conflicting reference %s ", str(desc)) return ua.StatusCode(ua.StatusCodes.BadReferenceNotAllowed) break # ref already exists else: nodedata.references.append(desc) return ua.StatusCode()
def _add_node(self, item, user): result = ua.AddNodesResult() if item.RequestedNewNodeId in self._aspace: self.logger.warning("AddNodeItem: node already exists") result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists) return result nodedata = NodeData(item.RequestedNewNodeId) # add common attrs nodedata.attributes[ua.AttributeIds.NodeId] = AttributeValue(ua.DataValue(ua.Variant(item.RequestedNewNodeId, ua.VariantType.NodeId))) nodedata.attributes[ua.AttributeIds.BrowseName] = AttributeValue(ua.DataValue(ua.Variant(item.BrowseName, ua.VariantType.QualifiedName))) nodedata.attributes[ua.AttributeIds.NodeClass] = AttributeValue(ua.DataValue(ua.Variant(item.NodeClass, ua.VariantType.Int32))) # add requested attrs self._add_nodeattributes(item.NodeAttributes, nodedata) # add parent if item.ParentNodeId == ua.NodeId(): #self.logger.warning("add_node: creating node %s without parent", item.RequestedNewNodeId) pass elif item.ParentNodeId not in self._aspace: #self.logger.warning("add_node: while adding node %s, requested parent node %s does not exists", item.RequestedNewNodeId, item.ParentNodeId) result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid) return result else: if not user == User.Admin: result.StatusCode = ua.StatusCode(ua.StatusCodes.BadUserAccessDenied) return result desc = ua.ReferenceDescription() desc.ReferenceTypeId = item.ReferenceTypeId desc.NodeId = item.RequestedNewNodeId desc.NodeClass = item.NodeClass desc.BrowseName = item.BrowseName desc.DisplayName = ua.LocalizedText(item.BrowseName.Name) desc.TypeDefinition = item.TypeDefinition desc.IsForward = True self._aspace[item.ParentNodeId].references.append(desc) # now add our node to db self._aspace[item.RequestedNewNodeId] = nodedata # add type definition if item.TypeDefinition != ua.NodeId(): addref = ua.AddReferencesItem() addref.SourceNodeId = item.RequestedNewNodeId addref.IsForward = True addref.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasTypeDefinition) addref.TargetNodeId = item.TypeDefinition addref.TargetNodeClass = ua.NodeClass.DataType self._add_reference(addref, user) result.StatusCode = ua.StatusCode() result.AddedNodeId = item.RequestedNewNodeId return result
def _delete_unique_reference(self, item, invert=False): if invert: source, target, forward = item.TargetNodeId, item.SourceNodeId, not item.IsForward else: source, target, forward = item.SourceNodeId, item.TargetNodeId, item.IsForward for rdesc in self._aspace[source].references: if rdesc.NodeId == target and rdesc.ReferenceTypeId == item.ReferenceTypeId: if rdesc.IsForward == forward: self._aspace[source].references.remove(rdesc) return ua.StatusCode() return ua.StatusCode(ua.StatusCodes.BadNotFound)
def test_status_code_to_string(self): # serialize a status code and deserialize it, name and doc resolution should work just fine statuscode = ua.StatusCode(ua.StatusCodes.BadNotConnected) statuscode2 = struct_from_binary(ua.StatusCode, io.BytesIO(struct_to_binary(ua.StatusCode(ua.StatusCodes.BadNotConnected)))) self.assertEqual(statuscode, statuscode2) self.assertEqual(statuscode.value, statuscode2.value) # properties that are not serialized should still translate properly self.assertEqual(statuscode.name, statuscode2.name) self.assertEqual(statuscode.doc, statuscode2.doc)
def _add_node(self, item, user, check=True): self.logger.debug("Adding node %s %s", item.RequestedNewNodeId, item.BrowseName) result = ua.AddNodesResult() if not user == User.Admin: result.StatusCode = ua.StatusCode(ua.StatusCodes.BadUserAccessDenied) return result if item.RequestedNewNodeId.has_null_identifier(): # If Identifier of requested NodeId is null we generate a new NodeId using # the namespace of the nodeid, this is an extention of the spec to allow # to requests the server to generate a new nodeid in a specified namespace self.logger.debug("RequestedNewNodeId has null identifier, generating Identifier") item.RequestedNewNodeId = self._aspace.generate_nodeid(item.RequestedNewNodeId.NamespaceIndex) else: if item.RequestedNewNodeId in self._aspace: self.logger.warning("AddNodesItem: Requested NodeId %s already exists", item.RequestedNewNodeId) result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists) return result if item.ParentNodeId.is_null(): self.logger.info("add_node: while adding node %s, requested parent node is null %s %s", item.RequestedNewNodeId, item.ParentNodeId, item.ParentNodeId.is_null()) if check: result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid) return result parentdata = self._aspace.get(item.ParentNodeId) if parentdata is None and not item.ParentNodeId.is_null(): self.logger.info("add_node: while adding node %s, requested parent node %s does not exists", item.RequestedNewNodeId, item.ParentNodeId) result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid) return result nodedata = NodeData(item.RequestedNewNodeId) self._add_node_attributes(nodedata, item, add_timestamps=check) # now add our node to db self._aspace[nodedata.nodeid] = nodedata if parentdata is not None: self._add_ref_from_parent(nodedata, item, parentdata) self._add_ref_to_parent(nodedata, item, parentdata) # add type definition if item.TypeDefinition != ua.NodeId(): self._add_type_definition(nodedata, item) result.StatusCode = ua.StatusCode() result.AddedNodeId = nodedata.nodeid return result
def delete_subscriptions(self, ids): self.logger.info("delete subscriptions: %s", ids) res = [] for i in ids: with self._lock: if i not in self.subscriptions: res.append(ua.StatusCode(ua.StatusCodes.BadSubscriptionIdInvalid)) else: sub = self.subscriptions.pop(i) sub.stop() res.append(ua.StatusCode()) return res
def turn_all_on(parent): if manualoperation.get_value() == True: c_sp1_open.set_value(True) c_sp2_open.set_value(True) c_sp3_open.set_value(True) f_sp1_open.set_value(True) f_sp2_open.set_value(True) f_sp3_open.set_value(True) pump_closed.set_value(False) pump_q.set_value(1) return ua.StatusCode(0) else: return ua.StatusCode(0x80000000) # Status code for Bad error
def _delete_reference(self, item, user): if item.SourceNodeId not in self._aspace: return ua.StatusCode(ua.StatusCodes.BadSourceNodeIdInvalid) if item.TargetNodeId not in self._aspace: return ua.StatusCode(ua.StatusCodes.BadTargetNodeIdInvalid) if item.ReferenceTypeId not in self._aspace: return ua.StatusCode(ua.StatusCodes.BadReferenceTypeIdInvalid) if user != User.Admin: return ua.StatusCode(ua.StatusCodes.BadUserAccessDenied) if item.DeleteBidirectional: self._delete_unique_reference(item, True) return self._delete_unique_reference(item)
def _delete_monitored_items(self, mid): if not mid in self._monitored_items: return ua.StatusCode(ua.StatusCodes.BadMonitoredItemIdInvalid) for k, v in self._monitored_events.items(): if v == mid: self._monitored_events.pop(k) break for k, v in self._monitored_datachange.items(): if v == mid: self.aspace.delete_datachange_callback(k) self._monitored_datachange.pop(k) break self._monitored_items.pop(mid) return ua.StatusCode()
def add_datachange_callback(self, nodeid, attr, callback): with self._lock: self.logger.debug("set attr callback: %s %s %s", nodeid, attr, callback) if nodeid not in self._nodes: return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown), 0 node = self._nodes[nodeid] if attr not in node.attributes: return ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid), 0 attval = node.attributes[attr] self._datachange_callback_counter += 1 handle = self._datachange_callback_counter attval.datachange_callbacks[handle] = callback self._handle_to_attribute_map[handle] = (nodeid, attr) return ua.StatusCode(), handle
def __init__(self): self.BooleanValue = True self.SByteValue = 0 self.ByteValue = 0 self.Int16Value = 0 self.UInt16Value = 0 self.Int32Value = 0 self.UInt32Value = 0 self.Int64Value = 0 self.UInt64Value = 0 self.FloatValue = 0 self.DoubleValue = 0 self.StringValue = '' self.DateTimeValue = datetime.utcnow() self.GuidValue = uuid.uuid4() self.ByteStringValue = b'' self.XmlElementValue = ua.XmlElement() self.NodeIdValue = ua.NodeId() self.ExpandedNodeIdValue = ua.ExpandedNodeId() self.QualifiedNameValue = ua.QualifiedName() self.LocalizedTextValue = ua.LocalizedText() self.StatusCodeValue = ua.StatusCode() self.VariantValue = ua.Variant() self.EnumerationValue = 0 self.StructureValue = ua.ExtensionObject() self.Number = ua.Variant() self.Integer = ua.Variant() self.UInteger = ua.Variant()
def write(self, params): with self.aspace._lock: if params.NodesToWrite[0].NodeId.NamespaceIndex == 2 : if self.data_cache_state: logging.debug("--- DataCache Write ---") if self.initialization_cache: self.write_data_request(params.NodesToWrite[0].NodeId, params.NodesToWrite[0].Value.Value._value) return self.iserver.attribute_service.write(params, self.user) uncertain_status = ua.StatusCode(ua.StatusCodes.Uncertain) uncertain_response = self.iserver.attribute_service.write(params, self.user) uncertain_response[0] = uncertain_status #need to implement ack from onem2m side self.write_data_request(params.NodesToWrite[0].NodeId, params.NodesToWrite[0].Value.Value._value) return uncertain_response else: logging.debug("--- Direct Access Write ---") self.write_data_request(params.NodesToWrite[0].NodeId, params.NodesToWrite[0].Value.Value._value) return self.iserver.attribute_service.write(params, self.user) return self.iserver.attribute_service.write(params, self.user)
def get_attribute_value(self, nodeid, attr): with self._lock: self.logger.debug("get attr val: %s %s", nodeid, attr) if nodeid not in self._nodes: dv = ua.DataValue() dv.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) return dv node = self._nodes[nodeid] if attr not in node.attributes: dv = ua.DataValue() dv.StatusCode = ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid) return dv attval = node.attributes[attr] if attval.value_callback: return attval.value_callback() return attval.value
def read_node_history(self, node_id, start, end, nb_values): with self._lock: _c_read = self._conn.cursor() table = self._get_table_name(node_id) start_time, end_time, order, limit = self._get_bounds(start, end, nb_values) cont = None results = [] # select values from the database; recreate UA Variant from binary try: for row in _c_read.execute('SELECT * FROM "{tn}" WHERE "SourceTimestamp" BETWEEN ? AND ? ' 'ORDER BY "_Id" {dir} LIMIT ?'.format(tn=table, dir=order), (start_time, end_time, limit,)): # rebuild the data value object dv = ua.DataValue(variant_from_binary(Buffer(row[6]))) dv.ServerTimestamp = row[1] dv.SourceTimestamp = row[2] dv.StatusCode = ua.StatusCode(row[3]) results.append(dv) except sqlite3.Error as e: self.logger.error('Historizing SQL Read Error for %s: %s', node_id, e) if nb_values: if len(results) > nb_values: cont = results[nb_values].SourceTimestamp results = results[:nb_values] return results, cont
def _read_history(self, details, rv): """ determine if the history read is for a data changes or events; then read the history for that node """ result = ua.HistoryReadResult() if isinstance(details, ua.ReadRawModifiedDetails): if details.IsReadModified: result.HistoryData = ua.HistoryModifiedData() # we do not support modified history by design so we return what we have else: result.HistoryData = ua.HistoryData() dv, cont = self._read_datavalue_history(rv, details) result.HistoryData.DataValues = dv result.ContinuationPoint = cont elif isinstance(details, ua.ReadEventDetails): result.HistoryData = ua.HistoryEvent() # FIXME: filter is a cumbersome type, maybe transform it something easier # to handle for storage ev, cont = self._read_event_history(rv, details) result.HistoryData.Events = ev result.ContinuationPoint = cont else: # we do not currently support the other types, clients can process data themselves result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNotImplemented) return result