-
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
811f4f4
commit be3bdf8
Showing
11 changed files
with
2,233 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, | ||
"int8": XSD.byte, | ||
"uint16": XSD.unsignedShort, | ||
"int16": XSD.short, | ||
"uint32": XSD.unsignedInt, | ||
"int32": XSD.int, | ||
"uint64": XSD.unsignedLong, | ||
"int64": XSD.long, | ||
"boolean": XSD.boolean, | ||
"float": XSD.float, | ||
"double": XSD.double, | ||
"string": XSD.string, | ||
"dateTime": XSD.dateTime, | ||
"dateTimeStamp": XSD.dateTimeStamp, | ||
"iso8601": XSD.dateTimeStamp, | ||
"anyURI": XSD.anyURI | ||
} | ||
|
||
DataUnits = { | ||
"cm3": get_unit_uri("cubicCentimetre"), | ||
"cm^3": get_unit_uri("cubicCentimetre"), | ||
"kw": get_unit_uri("kilowatt"), | ||
"kW": get_unit_uri("kilowatt"), | ||
"kWh": get_unit_uri("kilowattHour"), | ||
"l": get_unit_uri("litre"), | ||
"l/100km" : get_unit_uri("litrePerHour"), | ||
"mm": get_unit_uri("millimetre"), | ||
"kg": get_unit_uri("kilogram"), | ||
"inch": get_unit_uri("inch"), | ||
"A": get_unit_uri("ampere"), | ||
"Ah": get_unit_uri("ampereHour"), | ||
"Nm": get_unit_uri("newtonMetre"), | ||
"N.m": get_unit_uri("newtonMetre"), | ||
"V": get_unit_uri("volt"), | ||
"celsius": get_unit_uri("degreeCelsius"), | ||
"cm/s": get_unit_uri("centimetrePerSecond"), | ||
"degree" : get_unit_uri("degreeUnitOfAngle"), | ||
"degrees": get_unit_uri("degreeUnitOfAngle"), | ||
"degrees/s": get_unit_uri("degreePerSecond"), | ||
"g/s": get_unit_uri("gramPerSecond"), | ||
"kilometer": get_unit_uri("kilometre"), | ||
"km": get_unit_uri("kilometre"), | ||
"km/h": get_unit_uri("kilometrePerHour"), | ||
"kpa": get_unit_uri("kilopascal"), | ||
"kPa": get_unit_uri("kilopascal"), | ||
"l/h": get_unit_uri("litrePerHour"), | ||
"m": get_unit_uri("metre"), | ||
"m/s": get_unit_uri("metrePerSecond"), | ||
"m/s2": get_unit_uri("metrePerSecondSquared"), | ||
"m/s^2": get_unit_uri("metrePerSecondSquared"), | ||
"mbar": get_unit_uri("millibar"), | ||
"min": get_unit_uri("minuteUnitOfTime"), | ||
"ml": get_unit_uri("millilitre"), | ||
"pa": get_unit_uri("pascal"), | ||
"Pa": get_unit_uri("pascal"), | ||
"percent": get_unit_uri("percent"), | ||
"percentage": get_unit_uri("percent"), | ||
"ratio": get_unit_uri("rate"), | ||
"rpm": get_unit_uri("revolutionsPerMinute"), | ||
"g/km": get_unit_uri("kilogramPerKilometre"), | ||
"s": get_unit_uri("secondUnitOfTime"), | ||
"h": get_unit_uri("secondUnitOfTime"), | ||
"W": get_unit_uri("watt"), | ||
"cpm": get_unit_uri("cycle"), | ||
"bpm": get_unit_uri("cycle"), | ||
"iso8601": get_unit_uri("secondUnitOfTime"), | ||
"blank": get_unit_uri("blank") | ||
} |
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 pathlib import Path | ||
from rdflib import Graph | ||
from vss_tools import log | ||
from ..config import config as cfg | ||
|
||
|
||
# Write RDF Graph data to specified file | ||
def write_graph_to_file(path_to_file: Path, file_name: str, graph: Graph): | ||
log.debug( | ||
"Writing RDF Graph to \n -- file: '%s' \n -- location: '%s'\n -- current working directory: '%s'\n", | ||
file_name, | ||
path_to_file, | ||
Path.cwd(), | ||
) # type: ignore | ||
|
||
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(cfg.CUSTOM_ESCAPE_CHAR, "\\") | ||
|
||
# Cleanup xsd:anyURI with xsd:double | ||
filedata = filedata.replace("xsd:anyURI", "xsd:double") | ||
|
||
# Create and open ttl file for writing | ||
output_file: Path = Path(f"{path_to_file}/{file_name}.ttl") | ||
|
||
# Make sure that output_file is created | ||
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() | ||
|
||
# Return file location | ||
return output_file |
43 changes: 43 additions & 0 deletions
43
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,43 @@ | ||
# 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 cfg | ||
|
||
|
||
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:{cfg.SAMM_VERSION}#{unit_name}") | ||
|
||
|
||
log.debug("VSS to SAMM CONFIG:\n -- SAMM_TYPE : %s\n -- SAMM_VERSION: %s\n", cfg.SAMM_TYPE, cfg.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:{cfg.SAMM_VERSION}#", | ||
"samm-c": f"{samm_base_namespace}:characteristic:{cfg.SAMM_VERSION}#", | ||
"samm-e": f"{samm_base_namespace}:entity:{cfg.SAMM_VERSION}#", | ||
"unit": f"{samm_base_namespace}:unit:{cfg.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}:{cfg.OUTPUT_NAMESPACE}:{cfg.VSPEC_VERSION}#" |
109 changes: 109 additions & 0 deletions
109
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,109 @@ | ||
# 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 cfg | ||
from . import stringHelper as str_helper | ||
from .namespaces import samm_base_namespace, samm_output_namespace | ||
|
||
class VSSConcepts(Enum): | ||
EMPTY = "" | ||
BELONGS_TO = "belongsToVehicleComponent" | ||
HAS_ATTRIBUTE = "hasStaticVehicleProperty" | ||
HAS_SIGNAL = "hasDynamicVehicleProperty" | ||
HAS_COMP_INST = "hasInstance" | ||
HOLDS_VALUE = "holdsState" | ||
PART_OF_VEHICLE = "partOfVehicle" | ||
PART_OF_VEH_COMP = "partOf" | ||
VEHICLE = "Vehicle" | ||
VEHICLE_ACT = "ActuatableVehicleProperty" | ||
VEHICLE_COMP = "VehicleComponent" | ||
VEHICLE_PROP = "DynamicVehicleProperty" | ||
VEHICLE_SIGNAL = "ObservableVehicleProperty" | ||
VEHICLE_STAT = "StaticVehicleProperty" | ||
|
||
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" | ||
CHARACTERISTIC = "Characteristic" | ||
CHARACTERISTIC_RELATION = "characteristic" | ||
DATA_TYPE = "dataType" | ||
DESCRIPTION = "description" | ||
ENTITY = "Entity" | ||
EVENTS = "events" | ||
EXAMPLE_VALUE = "exampleValue" | ||
NAME = "name" | ||
OPERATIONS = "operations" | ||
OPTIONAL = "optional" | ||
PAYLOAD_NAME = "payloadName" | ||
PREFERRED_NAME = "preferredName" | ||
PROPERTIES = "properties" | ||
PROPERTY = "Property" | ||
|
||
def __init__(self, vss_name): | ||
self.ns = f"{samm_base_namespace}:meta-model:{cfg.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}" | ||
|
||
@property | ||
def samm_name(self): | ||
# Make sure that enum value is lc_first | ||
return f"samm:{str_helper.str_to_lc_first_camel_case(self.value)}" | ||
|
||
|
||
class SammCConcepts(Enum): | ||
BASE_CHARACTERISTICS = "baseCharacteristic" | ||
BOOLEAN = "Boolean" | ||
CONSTRAINT = "constraint" | ||
DEFAULT_VALUE = "defaultValue" | ||
ENUM = "Enumeration" | ||
LIST = "List" | ||
MAX_VALUE = "maxValue" | ||
MEASUREMENT = "Measurement" | ||
MIN_VALUE = "minValue" | ||
QUANTIFIABLE = "Quantifiable" | ||
RANGE_CONSTRAINT = "RangeConstraint" | ||
SINGLE_ENTITY = "SingleEntity" | ||
STATE = "State" | ||
TIMESTAMP = "Timestamp" | ||
TRAIT = "Trait" | ||
UNIT = "unit" | ||
VALUES = "values" | ||
|
||
def __init__(self, vss_name): | ||
self.ns = f"{samm_base_namespace}:characteristic:{cfg.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.