-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SAMM - Semantic Aspect Meta Model exporter
Signed-off-by: Kostadin Ivanov (BD/TBC-BG) <kostadin.ivanov@bosch.com>
- Loading branch information
1 parent
13873cb
commit 5ebbf86
Showing
11 changed files
with
2,143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
src/vss_tools/vspec/vssexporters/vss2samm/config/config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright (c) 2024 Contributors to COVESA | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Mozilla Public License 2.0 which is available at | ||
# https://www.mozilla.org/en-US/MPL/2.0/ | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
# General CONFIG variables | ||
SAMM_TYPE = 'samm' | ||
SAMM_VERSION = '2.1.0' | ||
# Custom string, which we use to escape " and ' characters in VSS node description/comments | ||
# Used in fileHelper.write_graph_to_file to properly escape characters in filedata, before to write it to a file. | ||
CUSTOM_ESCAPE_CHAR = '#V2E-ESC-CHAR#' | ||
|
||
# CONFIG Variable defined at runtime as per user input and in available init function | ||
OUTPUT_NAMESPACE = None | ||
VSPEC_VERSION = None | ||
SPLIT_DEPTH = None | ||
|
||
|
||
def init(output_namespace: str, vspec_version: str, split_depth: int): | ||
|
||
# Set user defined or OUTPUT_NAMESPACE | ||
global OUTPUT_NAMESPACE | ||
OUTPUT_NAMESPACE = output_namespace | ||
|
||
# Set user defined or OUTPUT_NAMESPACE | ||
global VSPEC_VERSION | ||
VSPEC_VERSION = vspec_version | ||
|
||
# Make sure that split_depth is in correct type and value, else set it to DEFAULT: 1 | ||
global SPLIT_DEPTH | ||
SPLIT_DEPTH = split_depth if (type(split_depth) is int and split_depth > 0) else 1 |
80 changes: 80 additions & 0 deletions
80
src/vss_tools/vspec/vssexporters/vss2samm/helpers/dataTypesAndUnits.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Copyright (c) 2024 Contributors to COVESA | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Mozilla Public License 2.0 which is available at | ||
# https://www.mozilla.org/en-US/MPL/2.0/ | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
from rdflib import XSD | ||
from .namespaces import get_unit_uri | ||
|
||
DataTypes = { | ||
'uint8' : XSD.unsignedByte, # noqa: E203 | ||
'int8' : XSD.byte, # noqa: E203 | ||
'uint16' : XSD.unsignedShort, # noqa: E203 | ||
'int16' : XSD.short, # noqa: E203 | ||
'uint32' : XSD.unsignedInt, # noqa: E203 | ||
'int32' : XSD.int, # noqa: E203 | ||
'uint64' : XSD.unsignedLong, # noqa: E203 | ||
'int64' : XSD.long, # noqa: E203 | ||
'boolean' : XSD.boolean, # noqa: E203 | ||
'float' : XSD.float, # noqa: E203 | ||
'double' : XSD.double, # noqa: E203 | ||
'string' : XSD.string, # noqa: E203 | ||
'dateTime' : XSD.dateTime, # noqa: E203 | ||
'dateTimeStamp' : XSD.dateTimeStamp, # noqa: E203 | ||
'iso8601' : XSD.dateTimeStamp, # noqa: E203 | ||
'anyURI' : XSD.anyURI # noqa: E203 | ||
} | ||
|
||
DataUnits = { | ||
'cm3' : get_unit_uri('cubicCentimetre'), # noqa: E203 | ||
'cm^3' : get_unit_uri('cubicCentimetre'), # noqa: E203 | ||
'kw' : get_unit_uri('kilowatt'), # noqa: E203 | ||
'kW' : get_unit_uri('kilowatt'), # noqa: E203 | ||
'kWh' : get_unit_uri('kilowattHour'), # noqa: E203 | ||
'l' : get_unit_uri('litre'), # noqa: E203 | ||
'l/100km' : get_unit_uri('litrePerHour'), # noqa: E203 | ||
'mm' : get_unit_uri('millimetre'), # noqa: E203 | ||
'kg' : get_unit_uri('kilogram'), # noqa: E203 | ||
'inch' : get_unit_uri('inch'), # noqa: E203 | ||
'A' : get_unit_uri('ampere'), # noqa: E203 | ||
'Ah' : get_unit_uri('ampereHour'), # noqa: E203 | ||
'Nm' : get_unit_uri('newtonMetre'), # noqa: E203 | ||
'N.m' : get_unit_uri('newtonMetre'), # noqa: E203 | ||
'V' : get_unit_uri('volt'), # noqa: E203 | ||
'celsius' : get_unit_uri('degreeCelsius'), # noqa: E203 | ||
'cm/s' : get_unit_uri('centimetrePerSecond'), # noqa: E203 | ||
'degree' : get_unit_uri('degreeUnitOfAngle'), # noqa: E203 | ||
'degrees' : get_unit_uri('degreeUnitOfAngle'), # noqa: E203 | ||
'degrees/s' : get_unit_uri('degreePerSecond'), # noqa: E203 | ||
'g/s' : get_unit_uri('gramPerSecond'), # noqa: E203 | ||
'kilometer' : get_unit_uri('kilometre'), # noqa: E203 | ||
'km' : get_unit_uri('kilometre'), # noqa: E203 | ||
'km/h' : get_unit_uri('kilometrePerHour'), # noqa: E203 | ||
'kpa' : get_unit_uri('kilopascal'), # noqa: E203 | ||
'kPa' : get_unit_uri('kilopascal'), # noqa: E203 | ||
'l/h' : get_unit_uri('litrePerHour'), # noqa: E203 | ||
'm' : get_unit_uri('metre'), # noqa: E203 | ||
'm/s' : get_unit_uri('metrePerSecond'), # noqa: E203 | ||
'm/s2' : get_unit_uri('metrePerSecondSquared'), # noqa: E203 | ||
'm/s^2' : get_unit_uri('metrePerSecondSquared'), # noqa: E203 | ||
'mbar' : get_unit_uri('millibar'), # noqa: E203 | ||
'min' : get_unit_uri('minuteUnitOfTime'), # noqa: E203 | ||
'ml' : get_unit_uri('millilitre'), # noqa: E203 | ||
'pa' : get_unit_uri('pascal'), # noqa: E203 | ||
'Pa' : get_unit_uri('pascal'), # noqa: E203 | ||
'percent' : get_unit_uri('percent'), # noqa: E203 | ||
'percentage' : get_unit_uri('percent'), # noqa: E203 | ||
'ratio' : get_unit_uri('rate'), # noqa: E203 | ||
'rpm' : get_unit_uri('revolutionsPerMinute'), # noqa: E203 | ||
'g/km' : get_unit_uri('kilogramPerKilometre'), # noqa: E203 | ||
's' : get_unit_uri('secondUnitOfTime'), # noqa: E203 | ||
'h' : get_unit_uri('secondUnitOfTime'), # noqa: E203 | ||
'W' : get_unit_uri('watt'), # noqa: E203 | ||
'cpm' : get_unit_uri('cycle'), # noqa: E203 | ||
'bpm' : get_unit_uri('cycle'), # noqa: E203 | ||
'iso8601' : get_unit_uri('secondUnitOfTime'), # noqa: E203 | ||
'blank' : get_unit_uri('blank') # noqa: E203 | ||
} |
59 changes: 59 additions & 0 deletions
59
src/vss_tools/vspec/vssexporters/vss2samm/helpers/fileHelper.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Copyright (c) 2024 Contributors to COVESA | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Mozilla Public License 2.0 which is available at | ||
# https://www.mozilla.org/en-US/MPL/2.0/ | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
import os | ||
from rdflib import Graph | ||
from vss_tools import log | ||
from .. config import config as cnfg | ||
|
||
|
||
# Write RDF Graph data to specified file | ||
def write_graph_to_file(path_to_file: str, file_name: str, graph: Graph): | ||
|
||
log.debug("Writing graph to \n -- file: '%s' \n -- location: '%s'", file_name, path_to_file) | ||
|
||
log.debug("Current working directory: '%s'", os.getcwd()) | ||
|
||
filedata = graph.serialize(format='ttl') | ||
|
||
# Clean up entries like: samm:operations "()" OR samm:operations "( )" | ||
filedata = filedata.replace(' \"()\" ', ' () ') | ||
filedata = filedata.replace(' \"( )\" ', ' ( ) ') | ||
filedata = filedata.replace(' \"( ', ' ( ') | ||
filedata = filedata.replace(' )\" ', ' ) ') | ||
|
||
# Cleanup other escape characters, that were introduced automatically by some of used libraries/tools | ||
filedata = filedata.replace('\\', '') | ||
|
||
# Cleanup some CUSTOM ESCAPED, by this script characters. | ||
# Usually double and single quotes in node.description or node.comment field | ||
filedata = filedata.replace(cnfg.CUSTOM_ESCAPE_CHAR, '\\') | ||
|
||
# Cleanup xsd:anyURI with xsd:double | ||
filedata = filedata.replace('xsd:anyURI', 'xsd:double') | ||
|
||
# Make sure that path_to_file ends with a back slash: \ | ||
if not str(path_to_file).endswith('\\'): | ||
path_to_file = f"{path_to_file}\\" | ||
|
||
# Create and open ttl file for writing | ||
output_file = f"{path_to_file}{file_name}.ttl" | ||
os.makedirs(os.path.dirname(output_file), exist_ok=True) | ||
file_writer = open(output_file, "w") | ||
|
||
# Write filedata to file | ||
file_writer.write(filedata) | ||
|
||
# Add new line and close the file | ||
file_writer.write("\n") | ||
file_writer.close() | ||
|
||
log.debug("Output file: '%s'\n", output_file) | ||
|
||
# Return file location | ||
return output_file |
47 changes: 47 additions & 0 deletions
47
src/vss_tools/vspec/vssexporters/vss2samm/helpers/namespaces.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright (c) 2024 Contributors to COVESA | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Mozilla Public License 2.0 which is available at | ||
# https://www.mozilla.org/en-US/MPL/2.0/ | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
from rdflib import URIRef | ||
from vss_tools import log | ||
from .. config import config as cnfg | ||
|
||
|
||
def get_vspec_uri(node_name: str): | ||
return URIRef(f'{samm_output_namespace}{node_name}') | ||
|
||
|
||
def get_node_name_from_vspec_uri(node_uri: URIRef): | ||
return node_uri.replace(samm_output_namespace, '') | ||
|
||
|
||
def get_unit_uri(unit_name: str): | ||
return URIRef(f"{samm_base_namespace}:unit:{cnfg.SAMM_VERSION}#{unit_name}") | ||
|
||
|
||
log.debug( | ||
"VSS to SAMM CONFIG:\n\t -- SAMM_TYPE : %s\n\t -- SAMM_VERSION: %s", | ||
cnfg.SAMM_TYPE, | ||
cnfg.SAMM_VERSION | ||
) | ||
|
||
# NOTE: base_name is more for the ESMF core libraries | ||
# TODO: read https://eclipse-esmf.github.io/samm-specification/snapshot/namespaces.html | ||
# and make sure these are more abstract and can be configured for particular project we use | ||
samm_prefix = "urn:samm" | ||
samm_base_namespace = f"{samm_prefix}:org.eclipse.esmf.samm" | ||
Namespaces = { | ||
'samm': f"{samm_base_namespace}:meta-model:{cnfg.SAMM_VERSION}#", | ||
'samm-c': f"{samm_base_namespace}:characteristic:{cnfg.SAMM_VERSION}#", | ||
'samm-e': f"{samm_base_namespace}:entity:{cnfg.SAMM_VERSION}#", | ||
'unit': f"{samm_base_namespace}:unit:{cnfg.SAMM_VERSION}#", | ||
} | ||
|
||
# Below formatted namespace should look like: urn:samm:com.covesa.vss.spec:5.0.0# | ||
# and is used for the ":" bindings of the converted to TTLs, VSS Aspect models | ||
# that will refer to the user specified output_namespace | ||
samm_output_namespace = f"{samm_prefix}:{cnfg.OUTPUT_NAMESPACE}:{cnfg.VSPEC_VERSION}#" |
108 changes: 108 additions & 0 deletions
108
src/vss_tools/vspec/vssexporters/vss2samm/helpers/sammConcepts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Copyright (c) 2024 Contributors to COVESA | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Mozilla Public License 2.0 which is available at | ||
# https://www.mozilla.org/en-US/MPL/2.0/ | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
|
||
from enum import Enum | ||
from rdflib import URIRef | ||
|
||
from .. config import config as cnfg | ||
from . namespaces import samm_base_namespace, samm_output_namespace | ||
|
||
|
||
class VSSConcepts (Enum): | ||
EMPTY = "" # noqa: E221 | ||
BELONGS_TO = "belongsToVehicleComponent" # noqa: E221 | ||
HOLDS_VALUE = "holdsState" # noqa: E221 | ||
HAS_SIGNAL = "hasDynamicVehicleProperty" # noqa: E221 | ||
HAS_ATTRIBUTE = "hasStaticVehicleProperty" # noqa: E221 | ||
PART_OF_VEHICLE = "partOfVehicle" # noqa: E221 | ||
PART_OF_VEH_COMP = "partOf" # noqa: E221 | ||
HAS_COMP_INST = "hasInstance" # noqa: E221 | ||
VEHICLE = "Vehicle" # noqa: E221 | ||
VEHICLE_SIGNAL = "ObservableVehicleProperty" # noqa: E221 | ||
VEHICLE_ACT = "ActuatableVehicleProperty" # noqa: E221 | ||
VEHICLE_COMP = "VehicleComponent" # noqa: E221 | ||
VEHICLE_PROP = "DynamicVehicleProperty" # noqa: E221 | ||
VEHICLE_STAT = "StaticVehicleProperty" # noqa: E221 | ||
|
||
def __init__(self, vss_name): | ||
self.ns = samm_output_namespace | ||
self.vsso_name = vss_name | ||
|
||
@property | ||
def uri(self): | ||
return URIRef(self.uri_string) | ||
|
||
@property | ||
def uri_string(self): | ||
return f'{self.ns}{self.value}' | ||
|
||
|
||
class SammConcepts (Enum): | ||
ASPECT = "Aspect" # noqa: E221 | ||
PROPERTY = "Property" # noqa: E221 | ||
ENTITY = "Entity" # noqa: E221 | ||
CHARACTERISTIC = "Characteristic" # noqa: E221 | ||
NAME = "name" # noqa: E221 | ||
CHARACTERISTIC_RELATION = "characteristic" # noqa: E221 | ||
PREFERRED_NAME = "preferredName" # noqa: E221 | ||
PAYLOAD_NAME = "payloadName" # noqa: E221 | ||
DESCRIPTION = "description" # noqa: E221 | ||
PROPERTIES = "properties" # noqa: E221 | ||
OPERATIONS = "operations" # noqa: E221 | ||
EVENTS = "events" # noqa: E221 | ||
DATA_TYPE = "dataType" # noqa: E221 | ||
OPTIONAL = "optional" # noqa: E221 | ||
EXAMPLE_VALUE = "exampleValue" # noqa: E221 | ||
|
||
def __init__(self, vss_name): | ||
self.ns = f"{samm_base_namespace}:meta-model:{cnfg.SAMM_VERSION}#" | ||
self.vsso_name = vss_name | ||
|
||
@property | ||
def uri(self): | ||
return URIRef(self.uri_string) | ||
|
||
@property | ||
def uri_string(self): | ||
return f'{self.ns}{self.value}' | ||
|
||
|
||
class SammCConcepts (Enum): | ||
ASPECT = "Aspect" # noqa: E221 | ||
PROPERTY = "Property" # noqa: E221 | ||
ENTITY = "Entity" # noqa: E221 | ||
SINGLE_ENTITY = "SingleEntity" # noqa: E221 | ||
STATE = "State" # noqa: E221 | ||
TRAIT = "Trait" # noqa: E221 | ||
TIMESTAMP = "Timestamp" # noqa: E221 | ||
RANGE_CONSTRAINT = "RangeConstraint" # noqa: E221 | ||
MEASUREMENT = "Measurement" # noqa: E221 | ||
QUANTIFIABLE = "Quantifiable" # noqa: E221 | ||
LIST = "List" # noqa: E221 | ||
ENUM = "Enumeration" # noqa: E221 | ||
BOOLEAN = "Boolean" # noqa: E221 | ||
VALUES = "values" # noqa: E221 | ||
UNIT = "unit" # noqa: E221 | ||
CONSTRAINT = "constraint" # noqa: E221 | ||
BASE_CHARACTERISTICS = "baseCharacteristic" # noqa: E221 | ||
MAX_VALUE = "maxValue" # noqa: E221 | ||
MIN_VALUE = "minValue" # noqa: E221 | ||
DEFAULT_VALUE = "defaultValue" # noqa: E221 | ||
|
||
def __init__(self, vss_name): | ||
self.ns = f"{samm_base_namespace}:characteristic:{cnfg.SAMM_VERSION}#" | ||
self.vsso_name = vss_name | ||
|
||
@property | ||
def uri(self): | ||
return URIRef(self.uri_string) | ||
|
||
@property | ||
def uri_string(self): | ||
return f'{self.ns}{self.value}' |
Oops, something went wrong.