Source code for smia.aas_model.extended_submodel

import abc
import logging
import basyx.aas.model
from basyx.aas.model import SubmodelElementList, SubmodelElement, Operation, Submodel, RelationshipElement, \
    AnnotatedRelationshipElement, BasicEventElement, SubmodelElementCollection, Property, MultiLanguageProperty, \
    Range, Blob, File, ReferenceElement, Capability

from smia.aas_model.extended_aas import ExtendedGeneralMethods
from smia.logic.exceptions import AASModelOntologyError, AASModelReadingError
from smia.css_ontology.css_ontology_utils import CapabilitySkillOntologyInfo
from smia.utilities.smia_info import AssetInterfacesInfo

_logger = logging.getLogger(__name__)


[docs] class ExtendedSubmodel(Submodel): """This class contains methods to be added to Submodel class of Basyx Python SDK model."""
[docs] def print_submodel_information(self): print("Submodel information:") print("\tid: {}".format(self.id)) print("\tid_short: {}".format(self.id_short)) print("\tdisplayName: {}".format(self.display_name)) print("\tdescription: {}".format(self.description)) print("\tcategory: {}".format(self.category)) print("\tkind: {}".format(self.kind)) print("\tsemanticId: {}".format(self.semantic_id)) print("\tsupplementalSemanticId: {}".format(self.supplemental_semantic_id)) print("\tadministration: {}".format(ExtendedGeneralMethods.print_administration(self.administration))) print("\textension: " + "{}".format(ExtendedGeneralMethods.print_namespace_set(self.extension))) print("\tdataSpecifications: " + "{}".format( ExtendedGeneralMethods.print_data_specifications(self.embedded_data_specifications))) print("\tqualifiers: " + "{}".format(ExtendedGeneralMethods.print_namespace_set(self.qualifier)))
[docs] class ExtendedSubmodelElement(SubmodelElement): """This class contains methods to be added to SubmodelElement class of Basyx Python SDK model."""
[docs] def print_submodel_element_information(self): print("Submodel element information:") print("\tid_short: {}".format(self.id_short)) print("\tdescription: {}".format(self.description)) print("\tsemanticId: {}".format(self.semantic_id)) print("\tsupplementalSemanticId: {}".format(self.supplemental_semantic_id)) print("\tqualifiers: " + "{}".format(ExtendedGeneralMethods.print_namespace_set(self.qualifier)))
[docs] def get_qualifier_by_semantic_id(self, semantic_id_reference): if self.qualifier is None: return None else: for qualifier in self.qualifier: if qualifier.check_semantic_id_exist(semantic_id_reference): return qualifier return None
[docs] def get_parent_submodel(self): """ This method gets the submodel where the self SubmodelElement is defined. Returns: basyx.aas.model.Submodel: parent submodel in form of a Python object. """ if isinstance(self.parent, basyx.aas.model.Submodel): return self.parent else: return self.parent.get_parent_submodel()
[docs] def check_cap_skill_ontology_semantics_and_qualifiers(self): """ This method checks if the SubmodelElement of the Skill has the required semanticIDs and qualifiers defined in the Capability-Skill ontology. Returns: bool: result of the check (only True if both semanticIDs and qualifiers of Capability-Skill ontology exist). """ # It will be checked if the semantic id of the skill is valid within the ontology if self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_SKILL_IRI) is False: _logger.error("The skill {} has not valid semanticID regarding the " "Capability-Skill ontology.".format(self)) return False if self.check_cap_skill_ontology_qualifier_for_skills() is False: _logger.error("The skill {} has not valid qualifiers regarding the " "Capability-Skill ontology.".format(self)) return False return True
[docs] def check_cap_skill_ontology_qualifier_for_skills(self): """ This method checks if the SubmodelElement of the Skill has valid qualifiers defined in the Capability-Skil ontology. Returns: bool: result of the check (only True if the qualifier of Capability-Skill ontology exists). """ skill_qualifier = self.get_qualifier_by_type('SkillImplementationType') if skill_qualifier is not None: if skill_qualifier.value in ['STATE', 'TRIGGER', 'OPERATION', 'FUNCTIONBLOCK']: return True _logger.error("ERROR: the qualifier is not valid in the skill {}".format(self)) return False
[docs] def get_parent_ref_by_semantic_id(self, semantic_id): """ This method gets the reference of a parent element of the SubmodelElement by the semanticID. Args: semantic_id (str): semantic identifier of the parent element. Returns: basyx.aas.model.ModelReference: model reference of the parent element (None if the parent does not exist) """ parent_elem = self.parent while parent_elem: if parent_elem.check_semantic_id_exist(semantic_id): return basyx.aas.model.ModelReference.from_referable(parent_elem) else: parent_elem = parent_elem.parent return None
[docs] class ExtendedRelationshipElement(RelationshipElement):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("\tSpecific attributes of RelationshipElements:") print("\t\tfirst: {}".format(self.first)) print("\t\tsecond: {}".format(self.second))
[docs] class ExtendedAnnotatedRelationshipElement(AnnotatedRelationshipElement):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("\t\tannotation: {}".format(self.annotation))
[docs] def check_cap_skill_ontology_semantic_id(self): """ This method checks if the Capability has one of the required semanticIDs defined in the Capability-Skill ontology, exactly for Capabilities. Returns: bool: result of the check (only True if the semanticID of Capability-Skill ontology exists). """ if ((self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_CAPABILITY_IRI)) or (self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_ASSET_CAPABILITY_IRI)) or (self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_AGENT_CAPABILITY_IRI))): return True else: _logger.error("ERROR: the capability is not valid within the ontology.") return False
[docs] def check_cap_skill_ontology_qualifiers(self): """ This method checks if the Capability has valid qualifiers, defined in the Capability-Skil ontology. Returns: bool: result of the check (only True if the qualifier of Capability-Skill ontology exists). """ capability_qualifier = self.get_qualifier_by_type('ExpressionSemantic') if capability_qualifier is not None: if capability_qualifier.value in ['REQUIREMENT', 'OFFER', 'ASSURANCE']: return True _logger.error("ERROR: the qualifier is not valid in the capability {}".format(self)) return False
[docs] def get_capability_type_in_ontology(self): """ This method gets the type of the capability within the Capability-Skill ontology. Returns: str: value of the type of the capability within the Capability-Skill ontology. """ if self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_CAPABILITY_IRI): return 'ManufacturingCapability' elif self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_ASSET_CAPABILITY_IRI): return 'AssetCapability' elif self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_AGENT_CAPABILITY_IRI): return 'AgentCapability' else: _logger.error("ERROR: the capability type is not valid within the ontology.") return None
[docs] def get_semantic_id_of_css_ontology(self): """ This method gets the semanticID of the capability within the Capability-Skill ontology. Returns: str: value of the semanticID of the capability within the Capability-Skill ontology. """ if self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_CAPABILITY_IRI): return CapabilitySkillOntologyInfo.CSS_ONTOLOGY_CAPABILITY_IRI elif self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_AGENT_CAPABILITY_IRI): return CapabilitySkillOntologyInfo.CSS_ONTOLOGY_AGENT_CAPABILITY_IRI elif self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_ASSET_CAPABILITY_IRI): return CapabilitySkillOntologyInfo.CSS_ONTOLOGY_ASSET_CAPABILITY_IRI else: raise AASModelOntologyError("The capability {} does not have a valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] class ExtendedOperation(Operation):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("\tSpecific attributes of Operations:") print("\t\tinputVariable: {}".format(ExtendedGeneralMethods.print_namespace_set(self.input_variable))) print("\t\toutputVariable: {}".format(ExtendedGeneralMethods.print_namespace_set(self.output_variable))) print("\t\tinoutputVariable: {}".format(ExtendedGeneralMethods.print_namespace_set(self.in_output_variable)))
[docs] def get_variable_value_id(self, value_id): """ This method gets the variable of the Operation that matches with the given valueId. Args: value_id (str): the value id of the variable to find. Returns: (str): id_short of the variable """ all_variables = [self.input_variable, self.output_variable, self.in_output_variable] for var_type_set in all_variables: for var in var_type_set: if var.value_id: for key in var.value_id.key: if key.value == value_id: return var.id_short return None
[docs] def get_operation_variables_by_semantic_id(self, semantic_id): """ This method gets all operation variables that have the given semanticID. Args: semantic_id (str): semantic identifier of the operation variables to find. Returns: list: all valid operation variables in form of a list of SubmodelElements. """ operation_variables = [] all_var_sets = [self.input_variable, self.output_variable, self.in_output_variable] for var_set in all_var_sets: for operation_variable in var_set: if operation_variable.check_semantic_id_exist(semantic_id): operation_variables.append(operation_variable) return operation_variables
[docs] class ExtendedBasicEventElement(BasicEventElement):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of BasicEventElements:")
# TODO
[docs] class ExtendedEntity: # class ExtendedEntity(Entity):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("\tSpecific attributes of Entities:") print("\t\tstatement: {}".format(self.statement)) print("\t\tentityType: {}".format(self.entity_type)) print("\t\tglobalAssetId: {}".format(self.global_asset_id)) print("\t\tspecificAssetId: {}".format(self.specific_asset_id))
[docs] class ExtendedSubmodelElementList(SubmodelElementList):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of SubmodelElementLists:")
# TODO
[docs] class ExtendedSubmodelElementCollection(SubmodelElementCollection):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("\tSpecific attributes of SubmodelElementCollections:") print("\t\tvalue: (SME in the collection)") for sm_elem_in_collection in self.value: print("\t\t\tSubmodelElement: {}".format(sm_elem_in_collection))
[docs] def get_sm_element_by_id_short(self, id_short): """ This method gets a submodel element inside a SubmodelElementCollection by its id_short. Args: id_short (str): id_short of the submodel element to find. Returns: basyx.aas.model.SubmodelElement: submodel element in form of Python object. """ return self.value.get('id_short', id_short)
[docs] def get_sm_element_by_semantic_id(self, semantic_id_ref): """ This method gets a submodel element inside a SubmodelElementCollection by its semantic identifier. Args: semantic_id_ref (str): semantic identifier of the submodel element to find. Returns: basyx.aas.model.SubmodelElement: submodel element in form of Python object. """ for sm_elem in self.value: for reference in sm_elem.semantic_id.key: if reference.value == semantic_id_ref: return sm_elem return None
# ------------ # DataElements # ------------
[docs] class ExtendedProperty(Property): """This class contains methods to be added to Property class of Basyx Python SDK model."""
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("Specific attributes of Properties:") print("\t\tvalueType: {}".format(self.value_type)) print("\t\tvalueId: {}".format(self.value_id)) print("\t\tvalue: {}".format(self.value))
[docs] class ExtendedMultiLanguageProperty(MultiLanguageProperty):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("Specific attributes of MultiLanguageProperties:") print("\t\tvalueId: {}".format(self.value_id)) print("\t\tvalue: {}".format(self.value))
[docs] class ExtendedRange(Range):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of Ranges:")
# TODO
[docs] class ExtendedBlob(Blob):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of Blobs:")
# TODO
[docs] class ExtendedFile(File):
[docs] def print_submodel_element_information(self): ExtendedSubmodelElement.print_submodel_element_information(self) print("Specific attributes of Files:") print("\t\tvalue: {}".format(self.value)) print("\t\tcontentType: {}".format(self.content_type))
[docs] class ExtendedReferenceElement(ReferenceElement):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of ReferenceElements:")
# TODO # CLASSES FOR CSS ONTOLOGY-BASED SOFTWARE # ----------------------------------------
[docs] class ExtendedGenericCSSClass(metaclass=abc.ABCMeta):
[docs] def add_old_sme_class(self, sme_class): """ This method adds the old Basyx SubmodelElement class to be stored to the correct execution of the software. Args: sme_class (basyx.aas.model.SubmodelElement): old submodel element class in BaSyx Python structure. """ self.old_sme_class = sme_class
# if issubclass(self.old_sme_class, basyx.aas.model.Operation): # print("Antes la Skill era una Operation") # if issubclass(self.old_sme_class, basyx.aas.model.SubmodelElement): # print("Antes la Skill era una SubmodelElement")
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ pass
[docs] class ExtendedCapability(ExtendedGenericCSSClass, Capability):
[docs] def print_submodel_element_information(self): super().print_submodel_element_information() print("Specific attributes of Capabilities:")
[docs] def check_cap_skill_ontology_semantics_and_qualifiers(self): """ This method checks if the Capability has the required semanticIDs and qualifiers defined in the Capability-Skill ontology, exactly for Capabilities. Returns: bool: result of the check (only True if both semanticIDs and qualifiers of Capability-Skill ontology exist). """ # It will be checked if the semantic id of the capability is valid within the ontology if self.check_cap_skill_ontology_semantic_id() is False: _logger.error("The capability {} has not valid semanticID regarding the " "Capability-Skill ontology.".format(self)) return False # It will also be checked if it has any of the qualifiers defined in the ontology for the capabilities if self.check_cap_skill_ontology_qualifiers() is False: _logger.error("The capability {} has not valid qualifiers regarding the " "Capability-Skill ontology.".format(self)) return False return True
[docs] class ExtendedSkill(ExtendedGenericCSSClass): # TODO se ha tenido que separar las skills simples (Operation,Event...) de las complejas (Submodel). De # momento estas no se han implementado pero en el White paper de PLattform Industrie se menciona que las Skills # se pueden implementar mediante FunctionBlock (Submodelo) pass
[docs] class ExtendedSkillInterface(ExtendedGenericCSSClass): # TODO se ha tenido que separar las skills interfaces simples (Operation,Event...) de las complejas (SMC). De # momento se tienen ambas opciones ya que las interfaces de servicios de activos son SMC y las de los servicios de # agente son simples
[docs] def get_associated_asset_interface(self): """ This method gets the asset interface AAS SubmodelElement associated with this skill interface. Returns: basyx.aas.model.SubmodelElement: submodel element of the asset interface. """ pass
[docs] class ExtendedCapabilityConstraint(ExtendedGenericCSSClass, ExtendedSubmodelElement, ExtendedProperty):
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ if not self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_CAPABILITY_CONSTRAINT_IRI): raise AASModelOntologyError("The skill {} does not have the valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] class ExtendedSimpleSkill(ExtendedSkill, ExtendedSubmodelElement, ExtendedOperation):
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ if not self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_SKILL_IRI): raise AASModelOntologyError("The skill {} does not have the valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] class ExtendedComplexSkill(ExtendedSkill, ExtendedSubmodel):
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ if not self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_SKILL_IRI): raise AASModelOntologyError("The skill {} does not have the valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] class ExtendedSkillParameter(ExtendedGenericCSSClass, ExtendedProperty): pass
[docs] class ExtendedSimpleSkillInterface(ExtendedSkillInterface, ExtendedOperation, ExtendedSubmodelElement):
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ if not self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_SKILL_INTERFACE_IRI): raise AASModelOntologyError("The skill {} does not have the valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] class ExtendedComplexSkillInterface(ExtendedSkillInterface, ExtendedSubmodelElementCollection):
[docs] def get_semantic_id_of_css_ontology(self): """ This method checks the semanticID of the skill within the Capability-Skill ontology. """ if not self.check_semantic_id_exist(CapabilitySkillOntologyInfo.CSS_ONTOLOGY_SKILL_INTERFACE_IRI): raise AASModelOntologyError("The skill {} does not have the valid semanticID within the " "ontology.".format(self.id_short), self, "OntologySemanticIdMissing")
[docs] def get_associated_asset_interface(self): """ This method gets the asset interface AAS SubmodelElement associated with this skill interface. Returns: basyx.aas.model.SubmodelElement: submodel element of the asset interface. """ # asset_interface_elem = self.get_parent_ref_by_semantic_id(AssetInterfacesInfo.SEMANTICID_INTERFACE) if asset_interface_elem is None: raise AASModelReadingError("The skill interface is not inside the AssetInterfaceSubmodel.", self, "SubmodelElementNotInValidSubmodel") return asset_interface_elem