diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7bfc06f..304cd07 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,6 +119,9 @@ else()
if (WIN32)
message("Use g++ compiler under Windows (mingw)...")
add_compile_definitions(UNICODE _UNICODE main=wmain)
+ # MinGW COFF object files can hit section limits for large translation units.
+ # Enable big object format to avoid assembler 'too many sections' failures.
+ add_compile_options(-Wa,-mbig-obj)
add_link_options(-municode)
else()
message("Use g++ compiler...")
diff --git a/README.md b/README.md
index 52737c9..8b86c76 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,20 @@
+The 'Eclipse Open Vehicle API' project is supported by Chips JU.
+
+
+
+
+
+The HAL4SDV project (Grant Agreement No. 101139789) is supported by the Chips Joint Undertaking and its members, including top-up funding by the national authorities.
+
+
+
+The Shift2SDV project (Grant Agreement No. 101194245) is supported by the Chips Joint Undertaking and its members, including top-up funding by the national authorities.
+
+
+
+---
+
+
# This is the latest news about 'Eclipse Open Vehicle API'
#
# for more information see documentation: https://eclipse.dev/openvehicle-api/
diff --git a/doxygen.config b/doxygen.config
index d7d3f12..6376615 100644
--- a/doxygen.config
+++ b/doxygen.config
@@ -1786,515 +1786,515 @@ MATHJAX_CODEFILE =
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing +. Also here use the
# to select a filter and or
- to activate or cancel the filter
- # option.
- # The default value is: YES.
- # This tag requires that the tag GENERATE_HTML is set to YES.
-
- SEARCHENGINE = YES
-
- # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
- # implemented using a web server instead of a web client using JavaScript. There
- # are two flavors of web server based searching depending on the EXTERNAL_SEARCH
- # setting. When disabled, doxygen will generate a PHP script for searching and
- # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
- # and searching needs to be provided by external tools. See the section
- # "External Indexing and Searching" for details.
- # The default value is: NO.
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- SERVER_BASED_SEARCH = NO
-
- # When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
- # script for searching. Instead the search results are written to an XML file
- # which needs to be processed by an external indexer. Doxygen will invoke an
- # external search engine pointed to by the SEARCHENGINE_URL option to obtain the
- # search results.
- #
- # Doxygen ships with an example indexer (doxyindexer) and search engine
- # (doxysearch.cgi) which are based on the open source search engine library
- # Xapian (see:
- # https://xapian.org/).
- #
- # See the section "External Indexing and Searching" for details.
- # The default value is: NO.
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- EXTERNAL_SEARCH = NO
-
- # The SEARCHENGINE_URL should point to a search engine hosted by a web server
- # which will return the search results when EXTERNAL_SEARCH is enabled.
- #
- # Doxygen ships with an example indexer (doxyindexer) and search engine
- # (doxysearch.cgi) which are based on the open source search engine library
- # Xapian (see:
- # https://xapian.org/). See the section "External Indexing and Searching" for
- # details.
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- SEARCHENGINE_URL =
-
- # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
- # search data is written to a file for indexing by an external tool. With the
- # SEARCHDATA_FILE tag the name of this file can be specified.
- # The default file is: searchdata.xml.
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- SEARCHDATA_FILE = searchdata.xml
-
- # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
- # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
- # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
- # projects and redirect the results back to the right project.
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- EXTERNAL_SEARCH_ID =
-
- # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
- # projects other than the one defined by this configuration file, but that are
- # all added to the same external search index. Each project needs to have a
- # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
- # to a relative location where the documentation can be found. The format is:
- # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
- # This tag requires that the tag SEARCHENGINE is set to YES.
-
- EXTRA_SEARCH_MAPPINGS =
-
- #---------------------------------------------------------------------------
- # Configuration options related to the LaTeX output
- #---------------------------------------------------------------------------
-
- # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
- # The default value is: YES.
-
- GENERATE_LATEX = NO
-
- # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
- # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
- # it.
- # The default directory is: latex.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_OUTPUT = latex
-
- # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
- # invoked.
- #
- # Note that when not enabling USE_PDFLATEX the default is latex when enabling
- # USE_PDFLATEX the default is pdflatex and when in the later case latex is
- # chosen this is overwritten by pdflatex. For specific output languages the
- # default can have been set differently, this depends on the implementation of
- # the output language.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_CMD_NAME = latex
-
- # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
- # index for LaTeX.
- # Note: This tag is used in the Makefile / make.bat.
- # See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
- # (.tex).
- # The default file is: makeindex.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- MAKEINDEX_CMD_NAME = makeindex
-
- # The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
- # generate index for LaTeX. In case there is no backslash (\) as first character
- # it will be automatically added in the LaTeX code.
- # Note: This tag is used in the generated output file (.tex).
- # See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
- # The default value is: makeindex.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_MAKEINDEX_CMD = makeindex
-
- # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
- # documents. This may be useful for small projects and may help to save some
- # trees in general.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- COMPACT_LATEX = NO
-
- # The PAPER_TYPE tag can be used to set the paper type that is used by the
- # printer.
- # Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
- # 14 inches) and executive (7.25 x 10.5 inches).
- # The default value is: a4.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- PAPER_TYPE = a4
-
- # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
- # that should be included in the LaTeX output. The package can be specified just
- # by its name or with the correct syntax as to be used with the LaTeX
- # \usepackage command. To get the times font for instance you can specify :
- # EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
- # To use the option intlimits with the amsmath package you can specify:
- # EXTRA_PACKAGES=[intlimits]{amsmath}
- # If left blank no extra packages will be included.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- EXTRA_PACKAGES =
-
- # The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
- # the generated LaTeX document. The header should contain everything until the
- # first chapter. If it is left blank doxygen will generate a standard header. It
- # is highly recommended to start with a default header using
- # doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
- # and then modify the file new_header.tex. See also section "Doxygen usage" for
- # information on how to generate the default header that doxygen normally uses.
- #
- # Note: Only use a user-defined header if you know what you are doing!
- # Note: The header is subject to change so you typically have to regenerate the
- # default header when upgrading to a newer version of doxygen. The following
- # commands have a special meaning inside the header (and footer): For a
- # description of the possible markers and block names see the documentation.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_HEADER =
-
- # The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
- # the generated LaTeX document. The footer should contain everything after the
- # last chapter. If it is left blank doxygen will generate a standard footer. See
- # LATEX_HEADER for more information on how to generate a default footer and what
- # special commands can be used inside the footer. See also section "Doxygen
- # usage" for information on how to generate the default footer that doxygen
- # normally uses. Note: Only use a user-defined footer if you know what you are
- # doing!
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_FOOTER =
-
- # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
- # LaTeX style sheets that are included after the standard style sheets created
- # by doxygen. Using this option one can overrule certain style aspects. Doxygen
- # will copy the style sheet files to the output directory.
- # Note: The order of the extra style sheet files is of importance (e.g. the last
- # style sheet in the list overrules the setting of the previous ones in the
- # list).
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_EXTRA_STYLESHEET =
-
- # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
- # other source files which should be copied to the LATEX_OUTPUT output
- # directory. Note that the files will be copied as-is; there are no commands or
- # markers available.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_EXTRA_FILES =
-
- # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
- # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
- # contain links (just like the HTML output) instead of page references. This
- # makes the output suitable for online browsing using a PDF viewer.
- # The default value is: YES.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- PDF_HYPERLINKS = YES
-
- # If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
- # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
- # files. Set this option to YES, to get a higher quality PDF documentation.
- #
- # See also section LATEX_CMD_NAME for selecting the engine.
- # The default value is: YES.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- USE_PDFLATEX = YES
-
- # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
- # command to the generated LaTeX files. This will instruct LaTeX to keep running
- # if errors occur, instead of asking the user for help.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_BATCHMODE = NO
-
- # If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
- # index chapters (such as File Index, Compound Index, etc.) in the output.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_HIDE_INDICES = NO
-
- # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
- # bibliography, e.g. plainnat, or ieeetr. See
- # https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
- # The default value is: plain.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_BIB_STYLE = plain
-
- # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
- # path from which the emoji images will be read. If a relative path is entered,
- # it will be relative to the LATEX_OUTPUT directory. If left blank the
- # LATEX_OUTPUT directory will be used.
- # This tag requires that the tag GENERATE_LATEX is set to YES.
-
- LATEX_EMOJI_DIRECTORY =
-
- #---------------------------------------------------------------------------
- # Configuration options related to the RTF output
- #---------------------------------------------------------------------------
-
- # If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
- # RTF output is optimized for Word 97 and may not look too pretty with other RTF
- # readers/editors.
- # The default value is: NO.
-
- GENERATE_RTF = NO
-
- # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
- # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
- # it.
- # The default directory is: rtf.
- # This tag requires that the tag GENERATE_RTF is set to YES.
-
- RTF_OUTPUT = rtf
-
- # If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
- # documents. This may be useful for small projects and may help to save some
- # trees in general.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_RTF is set to YES.
-
- COMPACT_RTF = NO
-
- # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
- # contain hyperlink fields. The RTF file will contain links (just like the HTML
- # output) instead of page references. This makes the output suitable for online
- # browsing using Word or some other Word compatible readers that support those
- # fields.
- #
- # Note: WordPad (write) and others do not support links.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_RTF is set to YES.
-
- RTF_HYPERLINKS = NO
+# to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
- # Load stylesheet definitions from file. Syntax is similar to doxygen's
- # configuration file, i.e. a series of assignments. You only have to provide
- # replacements, missing definitions are set to their default value.
- #
- # See also section "Doxygen usage" for information on how to generate the
- # default style sheet that doxygen normally uses.
- # This tag requires that the tag GENERATE_RTF is set to YES.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
- RTF_STYLESHEET_FILE =
-
- # Set optional variables used in the generation of an RTF document. Syntax is
- # similar to doxygen's configuration file. A template extensions file can be
- # generated using doxygen -e rtf extensionFile.
- # This tag requires that the tag GENERATE_RTF is set to YES.
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
- RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
- #---------------------------------------------------------------------------
- # Configuration options related to the man page output
- #---------------------------------------------------------------------------
-
- # If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
- # classes and files.
- # The default value is: NO.
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
- GENERATE_MAN = NO
+GENERATE_MAN = NO
- # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
- # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
- # it. A directory man3 will be created inside the directory specified by
- # MAN_OUTPUT.
- # The default directory is: man.
- # This tag requires that the tag GENERATE_MAN is set to YES.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
- MAN_OUTPUT = man
+MAN_OUTPUT = man
- # The MAN_EXTENSION tag determines the extension that is added to the generated
- # man pages. In case the manual section does not start with a number, the number
- # 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
- # optional.
- # The default value is: .3.
- # This tag requires that the tag GENERATE_MAN is set to YES.
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
- MAN_EXTENSION = .3
+MAN_EXTENSION = .3
- # The MAN_SUBDIR tag determines the name of the directory created within
- # MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
- # MAN_EXTENSION with the initial . removed.
- # This tag requires that the tag GENERATE_MAN is set to YES.
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
- MAN_SUBDIR =
-
- # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
- # will generate one additional man file for each entity documented in the real
- # man page(s). These additional files only source the real man page, but without
- # them the man command would be unable to find the correct page.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_MAN is set to YES.
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
- MAN_LINKS = NO
+MAN_LINKS = NO
- #---------------------------------------------------------------------------
- # Configuration options related to the XML output
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
- # If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
- # captures the structure of the code including all documentation.
- # The default value is: NO.
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
- GENERATE_XML = YES
+GENERATE_XML = YES
- # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
- # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
- # it.
- # The default directory is: xml.
- # This tag requires that the tag GENERATE_XML is set to YES.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
- XML_OUTPUT = xml
-
- # If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
- # listings (including syntax highlighting and cross-referencing information) to
- # the XML output. Note that enabling this will significantly increase the size
- # of the XML output.
- # The default value is: YES.
- # This tag requires that the tag GENERATE_XML is set to YES.
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
- XML_PROGRAMLISTING = YES
+XML_PROGRAMLISTING = YES
- # If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
- # namespace members in file scope as well, matching the HTML output.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_XML is set to YES.
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
- XML_NS_MEMB_FILE_SCOPE = NO
+XML_NS_MEMB_FILE_SCOPE = NO
- #---------------------------------------------------------------------------
- # Configuration options related to the DOCBOOK output
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
- # If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
- # that can be used to generate PDF.
- # The default value is: NO.
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
- GENERATE_DOCBOOK = NO
+GENERATE_DOCBOOK = NO
- # The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
- # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
- # front of it.
- # The default directory is: docbook.
- # This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
- DOCBOOK_OUTPUT = docbook
+DOCBOOK_OUTPUT = docbook
- #---------------------------------------------------------------------------
- # Configuration options for the AutoGen Definitions output
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
- # AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
- # the structure of the code including all documentation. Note that this feature
- # is still experimental and incomplete at the moment.
- # The default value is: NO.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
- GENERATE_AUTOGEN_DEF = NO
+GENERATE_AUTOGEN_DEF = NO
- #---------------------------------------------------------------------------
- # Configuration options related to the Perl module output
- #---------------------------------------------------------------------------
-
- # If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
- # file that captures the structure of the code including all documentation.
- #
- # Note that this feature is still experimental and incomplete at the moment.
- # The default value is: NO.
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
- GENERATE_PERLMOD = NO
-
- # If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
- # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
- # output from the Perl module output.
- # The default value is: NO.
- # This tag requires that the tag GENERATE_PERLMOD is set to YES.
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
- PERLMOD_LATEX = NO
+PERLMOD_LATEX = NO
- # If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
- # formatted so it can be parsed by a human reader. This is useful if you want to
- # understand what is going on. On the other hand, if this tag is set to NO, the
- # size of the Perl module output will be much smaller and Perl will parse it
- # just the same.
- # The default value is: YES.
- # This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
- PERLMOD_PRETTY = YES
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
- # The names of the make variables in the generated doxyrules.make file are
- # prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
- # so different doxyrules.make files included by the same Makefile don't
- # overwrite each other's variables.
- # This tag requires that the tag GENERATE_PERLMOD is set to YES.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
- PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
- #---------------------------------------------------------------------------
- # Configuration options related to the preprocessor
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
- # If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
- # C-preprocessor directives found in the sources and include files.
- # The default value is: YES.
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
- ENABLE_PREPROCESSING = YES
-
- # If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
- # in the source code. If set to NO, only conditional compilation will be
- # performed. Macro expansion can be done in a controlled way by setting
- # EXPAND_ONLY_PREDEF to YES.
- # The default value is: NO.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
- MACRO_EXPANSION = YES
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
- # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
- # the macro expansion is limited to the macros specified with the PREDEFINED and
- # EXPAND_AS_DEFINED tags.
- # The default value is: NO.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
- EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = NO
- # If the SEARCH_INCLUDES tag is set to YES, the include files in the
- # INCLUDE_PATH will be searched if a #include is found.
- # The default value is: YES.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
- SEARCH_INCLUDES = YES
-
- # The INCLUDE_PATH tag can be used to specify one or more directories that
- # contain include files that are not input files but should be processed by the
- # preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
- # RECURSIVE has no effect here.
- # This tag requires that the tag SEARCH_INCLUDES is set to YES.
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
- INCLUDE_PATH =
-
- # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
- # patterns (like *.h and *.hpp) to filter out the header-files in the
- # directories. If left blank, the patterns specified with FILE_PATTERNS will be
- # used.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
- INCLUDE_FILE_PATTERNS =
-
- # The PREDEFINED tag can be used to specify one or more macro names that are
- # defined before the preprocessor is started (similar to the -D option of e.g.
- # gcc). The argument of the tag is a list of macros of the form: name or
- # name=definition (no spaces). If the definition and the "=" are omitted, "=1"
- # is assumed. To prevent a macro definition from being undefined via #undef or
- # recursively expanded use the := operator instead of the = operator.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = DOXYGEN_IGNORE \
__declspec(x)= \
@@ -2307,7 +2307,7 @@ BEGIN_SDV_INTERFACE_MAP()= \
SDV_INTERFACE_ENTRY(x)= \
END_SDV_INTERFACE_MAP()= \
SDV_INTERFACE_USE_NAMESPACE(x)= \
-SDV_INTERFACE_ENTRY_MEMBER(x)= \
+SDV_INTERFACE_ENTRY_MEMBER(x, y)= \
SDV_INTERFACE_ENTRY_INDIRECT(x, y)= \
SDV_INTERFACE_DENY_ENTRY(x)= \
SDV_INTERFACE_CHAIN_BASE(x)= \
@@ -2317,94 +2317,119 @@ SDV_INTERFACE_SET_SECTION_CONDITION(x, y)= \
SDV_INTERFACE_SET_SECTION(x)= \
SDV_INTERFACE_DEFAULT_SECTION()= \
SDV_INTERFACE_SECTION(x)= \
+SDV_CONCAT_IMPL(a, b)= \
+SDV_CONCAT(a, b)= \
+SDV_UNIQUE_VAR(prefix)= \
+BEGIN_SDV_LABEL_MAP(enum_type)= \
+SDV_LABEL_ENTRY(enum_element, name_string)= \
+END_SDV_LABEL_MAP()= \
+BEGIN_SDV_PARAM_MAP()= \
+END_SDV_PARAM_MAP()= \
+SDV_PARAM_GROUP(group_string)= \
+SDV_PARAM_NO_GROUP()= \
+SDV_PARAM_RESET_ATTRIBUTES()= \
+SDV_PARAM_SET_READONLY()= \
+SDV_PARAM_RESET_READONLY()= \
+SDV_PARAM_ENABLE_LOCKING()= \
+SDV_PARAM_DISABLE_LOCKING()= \
+SDV_PARAM_SET_TEMPORARY()= \
+SDV_PARAM_RESET_TEMPORARY()= \
+SDV_PARAM_ENTRY(var, name_string, default_val, unit_string, description_string)= \
+SDV_PARAM_NUMBER_ENTRY(var, name_string, default_val, low_limit, high_limit, unit_string, description_string)= \
+SDV_PARAM_ENUM_ENTRY(var, name_string, default_val, description_string)= \
+SDV_PARAM_STRING_ENTRY(var, name_string, default_val, pattern_string, unit_string, description_string)= \
+SDV_PARAM_PATH_ENTRY(var, name_string, default_val, description_string)= \
+SDV_PARAM_BITMASK_ENTRY(TEnum, var, name_string, default_val, description_string)= \
+SDV_PARAM_CHAIN_BASE(base_class)= \
+SDV_PARAM_CHAIN_MEMBER(member)= \
DEFINE_SDV_OBJECT(x)= \
switch=
- # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
- # tag can be used to specify a list of macro names that should be expanded. The
- # macro definition that is found in the sources will be used. Use the PREDEFINED
- # tag if you want to use a different macro definition that overrules the
- # definition found in the source code.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
- EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
- # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
- # remove all references to function-like macros that are alone on a line, have
- # an all uppercase name, and do not end with a semicolon. Such function macros
- # are typically used for boiler-plate code, and will confuse the parser if not
- # removed.
- # The default value is: YES.
- # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
- SKIP_FUNCTION_MACROS = YES
+SKIP_FUNCTION_MACROS = YES
- #---------------------------------------------------------------------------
- # Configuration options related to external references
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
- # The TAGFILES tag can be used to specify one or more tag files. For each tag
- # file the location of the external documentation should be added. The format of
- # a tag file without this location is as follows:
- # TAGFILES = file1 file2 ...
- # Adding location for the tag files is done as follows:
- # TAGFILES = file1=loc1 "file2 = loc2" ...
- # where loc1 and loc2 can be relative or absolute paths or URLs. See the
- # section "Linking to external documentation" for more information about the use
- # of tag files.
- # Note: Each tag file must have a unique name (where the name does NOT include
- # the path). If a tag file is not located in the directory in which doxygen is
- # run, you must also specify the path to the tagfile here.
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
- TAGFILES =
+TAGFILES =
- # When a file name is specified after GENERATE_TAGFILE, doxygen will create a
- # tag file that is based on the input files it reads. See section "Linking to
- # external documentation" for more information about the usage of tag files.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
- GENERATE_TAGFILE =
+GENERATE_TAGFILE =
- # If the ALLEXTERNALS tag is set to YES, all external class will be listed in
- # the class index. If set to NO, only the inherited external classes will be
- # listed.
- # The default value is: NO.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
- ALLEXTERNALS = NO
+ALLEXTERNALS = NO
- # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
- # in the modules index. If set to NO, only the current project's groups will be
- # listed.
- # The default value is: YES.
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
- EXTERNAL_GROUPS = YES
+EXTERNAL_GROUPS = YES
- # If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
- # the related pages index. If set to NO, only the current project's pages will
- # be listed.
- # The default value is: YES.
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
- EXTERNAL_PAGES = YES
+EXTERNAL_PAGES = YES
- #---------------------------------------------------------------------------
- # Configuration options related to the dot tool
- #---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
- # You can include diagrams made with dia in doxygen documentation. Doxygen will
- # then run dia to produce the diagram and insert it in the documentation. The
- # DIA_PATH tag allows you to specify the directory where the dia binary resides.
- # If left empty dia is assumed to be found in the default search path.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
- DIA_PATH =
+DIA_PATH =
- # If set to YES the inheritance and collaboration graphs will hide inheritance
- # and usage relations if the target is undocumented or is not a class.
- # The default value is: YES.
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
- HIDE_UNDOC_RELATIONS = YES
+HIDE_UNDOC_RELATIONS = YES
- # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
- # available from the path. This tool is part of Graphviz (see:
- # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
diff --git a/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.cpp b/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.cpp
index 40a2191..13d780a 100644
--- a/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.cpp
+++ b/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.cpp
@@ -353,7 +353,7 @@ void CConsole::StartUpdateDataThread()
m_bThreadStarted = true;
m_bRunning = true;
- m_threadReadTxSignals = std::thread(&CConsole::UpdateDataThreadFunc, this);
+ m_threadReadTxSignals = sdv::core::secure_thread(&CConsole::UpdateDataThreadFunc, this);
}
void CConsole::StopUpdateDataThread()
diff --git a/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.h b/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.h
index ab13c36..ec35250 100644
--- a/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.h
+++ b/examples/auto_headlamp_example/autoheadlight_app/autoheadlight_console.h
@@ -200,33 +200,33 @@ private:
*/
std::string AlignString(const std::string& message, uint32_t desiredLength = 0);
- mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
- std::thread m_threadReadTxSignals; ///< Simulation datalink thread.
- bool m_bThreadStarted = false; ///< Set when initialized.
- std::atomic_bool m_bRunning = false; ///< When set, the application is running.
+ mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
+ sdv::core::secure_thread m_threadReadTxSignals; ///< Simulation datalink thread.
+ bool m_bThreadStarted = false; ///< Set when initialized.
+ std::atomic_bool m_bRunning = false; ///< When set, the application is running.
- sdv::core::CSignal m_signalCurrentLatitude; ///< Signal Current latitude
- sdv::core::CSignal m_signalCurrentLongitude; ///< Signal Current longitude
- sdv::core::CSignal m_signalHeadlight; ///< Signal Headlight status
+ sdv::core::CSignal m_signalCurrentLatitude; ///< Signal Current latitude
+ sdv::core::CSignal m_signalCurrentLongitude; ///< Signal Current longitude
+ sdv::core::CSignal m_signalHeadlight; ///< Signal Headlight status
- float m_fCurrentLongitude = 0.0f; //< Current latitude
- float m_fCurrentLatitude = 0.0f; //< Current longitude
- bool m_bHeadLight = true; ///< Head light
+ float m_fCurrentLongitude = 0.0f; //< Current latitude
+ float m_fCurrentLatitude = 0.0f; //< Current longitude
+ bool m_bHeadLight = true; ///< Head light
- float m_fVehicleDeviceCurrentLatitude = 0.0f; ///< Current latitude (Vehicle Device)
- float m_fVehicleDeviceCurrentLongitude = 0.0; ///< Current longitude (Vehicle Device)
+ float m_fVehicleDeviceCurrentLatitude = 0.0f; ///< Current latitude (Vehicle Device)
+ float m_fVehicleDeviceCurrentLongitude = 0.0; ///< Current longitude (Vehicle Device)
- float m_fBasicServiceCurrentLatitude = 0.0f; ///< Current latitude (basic Service)
- float m_fBasicServiceCurrentLongitude = 0.0; ///< Current longitude (basic Service)
+ float m_fBasicServiceCurrentLatitude = 0.0f; ///< Current latitude (basic Service)
+ float m_fBasicServiceCurrentLongitude = 0.0; ///< Current longitude (basic Service)
- IAutoheadlightService* m_pIAutoheadlightComplexService = nullptr; ///< Autoheadlight Service interface pointer.
+ IAutoheadlightService* m_pIAutoheadlightComplexService = nullptr; ///< Autoheadlight Service interface pointer.
#ifdef _WIN32
- DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
- DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
+ DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
+ DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
#elif defined __unix__
- struct termios m_sTermAttr {}; ///< The terminal attributes before disabling echo.
+ struct termios m_sTermAttr {}; ///< The terminal attributes before disabling echo.
int m_iFileStatus = 0; ///< The file status flags for STDIN.
#else
#error The OS is not supported!
diff --git a/examples/auto_headlamp_example/fmu_files/model.cpp b/examples/auto_headlamp_example/fmu_files/model.cpp
index ad6b52c..524a9e0 100644
--- a/examples/auto_headlamp_example/fmu_files/model.cpp
+++ b/examples/auto_headlamp_example/fmu_files/model.cpp
@@ -94,7 +94,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
- tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
+ tomlFile << R"toml(# Location of the SDV binaries and configuration files
+[CoreLocation]
+Version = 100
+Framework = ")toml";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
diff --git a/examples/door_demo_example/CMakeLists.txt b/examples/door_demo_example/CMakeLists.txt
index cbc7141..65e2043 100644
--- a/examples/door_demo_example/CMakeLists.txt
+++ b/examples/door_demo_example/CMakeLists.txt
@@ -43,59 +43,63 @@ file (COPY ${PROJECT_SOURCE_DIR}/door_example_receiver.asc DESTINATION ${CMAKE_B
######################################################################################################################################################################
# Execute sdv_vss_util to create IDL files for devices and basic services.
+# In this example we split into into front and rear (frontdoors_proxystub.sdv and frontdoors_proxystub.sdv)
+# because all interfaces combined in doors_proxystub.sdv would be to large
message("Create interface code for devices and basic services of doors example.")
-execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/" --prefixdoors --version1.0.0.1 --enable_components)
+execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_front_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/front/" --prefixfrontdoors --version1.0.0.1 --enable_components)
+execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_rear_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/rear/" --prefixreardoors --version1.0.0.1 --enable_components)
message("Compiling Interface Door01Left RX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
message("Compiling Interface Door01Right RX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
-
-message("Compiling Interface Door02Left RX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
-
-message("Compiling Interface Door02Right RX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
-
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
message("Compiling Interface Door01Left TX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
message("Compiling Interface Door01Right TX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
+
+
+message("Compiling Interface Door02Left RX")
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
+
+message("Compiling Interface Door02Right RX")
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
message("Compiling Interface Door02Left TX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
message("Compiling Interface Door02Right TX")
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
-execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
+execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
# Execute the IDL compiler for the complex service to digest interface code.
message("Compiling door_ifc.idl")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/door_service/door_ifc.idl" "-O${PROJECT_SOURCE_DIR}/generated/door_service/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Iexample_service/ --ps_lib_namedoors_service_proxystub)
add_subdirectory(generated/door_service/ps)
-add_subdirectory(generated/vss_files/ps)
+add_subdirectory(generated/front/vss_files/ps)
+add_subdirectory(generated/rear/vss_files/ps)
-add_subdirectory(generated/vss_files/vd_frontdoorleft)
-add_subdirectory(generated/vss_files/vd_frontdoorright)
-add_subdirectory(generated/vss_files/vd_reardoorleft)
-add_subdirectory(generated/vss_files/vd_reardoorright)
+add_subdirectory(generated/front/vss_files/vd_frontdoorleft)
+add_subdirectory(generated/front/vss_files/vd_frontdoorright)
+add_subdirectory(generated/front/vss_files/bs_frontdoorleft)
+add_subdirectory(generated/front/vss_files/bs_frontdoorright)
-add_subdirectory(generated/vss_files/bs_frontdoorleft)
-add_subdirectory(generated/vss_files/bs_frontdoorright)
-add_subdirectory(generated/vss_files/bs_reardoorleft)
-add_subdirectory(generated/vss_files/bs_reardoorright)
+add_subdirectory(generated/rear/vss_files/vd_reardoorleft)
+add_subdirectory(generated/rear/vss_files/vd_reardoorright)
+add_subdirectory(generated/rear/vss_files/bs_reardoorleft)
+add_subdirectory(generated/rear/vss_files/bs_reardoorright)
# Execute sdv_dbc_util to create data link code & FMU code.
message("Create data link for doors example")
@@ -167,7 +171,6 @@ else()
target_link_libraries(door_external_app Rpcrt4.lib)
endif()
-
######################################################################################################################################################################
# create instance 3002 of door demo example
######################################################################################################################################################################
@@ -175,23 +178,25 @@ add_custom_target(vehicle_device_doors_config
ALL
DEPENDS
can_dl_doors
- doors_vd_frontdoorleft_rx
- doors_vd_frontdoorright_rx
- doors_vd_reardoorleft_rx
- doors_vd_reardoorright_rx
- COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL VehicleDeviceDoors --instance3002 can_dl_doors.sdv doors_vd_frontdoorleft_rx.sdv doors_vd_frontdoorright_rx.sdv doors_vd_reardoorleft_rx.sdv doors_vd_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --interface_config --overwrite
+ frontdoors_vd_frontdoorleft_rx
+ frontdoors_vd_frontdoorright_rx
+ reardoors_vd_reardoorleft_rx
+ reardoors_vd_reardoorright_rx
+ COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL VehicleDeviceDoors --instance3002 can_dl_doors.sdv frontdoors_vd_frontdoorleft_rx.sdv frontdoors_vd_frontdoorright_rx.sdv reardoors_vd_reardoorleft_rx.sdv reardoors_vd_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --interface_config --overwrite
VERBATIM
)
+
add_custom_target(basic_service_doors_config
ALL
DEPENDS
- doors_proxystub
- doors_bs_frontdoorleft_rx
- doors_bs_frontdoorright_rx
- doors_bs_reardoorleft_rx
- doors_bs_reardoorright_rx
- COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL BasicServiceDoors --instance3002 doors_proxystub.sdv doors_bs_frontdoorleft_rx.sdv doors_bs_frontdoorright_rx.sdv doors_bs_reardoorleft_rx.sdv doors_bs_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --abstract_config --overwrite
+ frontdoors_proxystub
+ reardoors_proxystub
+ frontdoors_bs_frontdoorleft_rx
+ frontdoors_bs_frontdoorright_rx
+ reardoors_bs_reardoorleft_rx
+ reardoors_bs_reardoorright_rx
+ COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL BasicServiceDoors --instance3002 frontdoors_proxystub.sdv reardoors_proxystub.sdv frontdoors_bs_frontdoorleft_rx.sdv frontdoors_bs_frontdoorright_rx.sdv reardoors_bs_reardoorleft_rx.sdv reardoors_bs_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --abstract_config --overwrite
VERBATIM
)
diff --git a/examples/door_demo_example/config/front_left_door_example.toml b/examples/door_demo_example/config/front_left_door_example.toml
index dd6699c..3019feb 100644
--- a/examples/door_demo_example/config/front_left_door_example.toml
+++ b/examples/door_demo_example/config/front_left_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorleft_rx.sdv"
+Path = "frontdoors_vd_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
[[Component]]
-Path = "doors_bs_frontdoorleft_rx.sdv"
+Path = "frontdoors_bs_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
diff --git a/examples/door_demo_example/config/front_right_door_example.toml b/examples/door_demo_example/config/front_right_door_example.toml
index 68f14bd..bce3013 100644
--- a/examples/door_demo_example/config/front_right_door_example.toml
+++ b/examples/door_demo_example/config/front_right_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorright_rx.sdv"
+Path = "frontdoors_vd_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
[[Component]]
-Path = "doors_bs_frontdoorright_rx.sdv"
+Path = "frontdoors_bs_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
diff --git a/examples/door_demo_example/config/rear_left_door_example.toml b/examples/door_demo_example/config/rear_left_door_example.toml
index 2da09dd..e26f52d 100644
--- a/examples/door_demo_example/config/rear_left_door_example.toml
+++ b/examples/door_demo_example/config/rear_left_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_reardoorleft_rx.sdv"
+Path = "reardoors_vd_reardoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Left_Device"
[[Component]]
-Path = "doors_bs_reardoorleft_rx.sdv"
+Path = "reardoors_bs_reardoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Left_Service"
diff --git a/examples/door_demo_example/config/rear_right_door_example.toml b/examples/door_demo_example/config/rear_right_door_example.toml
index 4f2069e..64acf61 100644
--- a/examples/door_demo_example/config/rear_right_door_example.toml
+++ b/examples/door_demo_example/config/rear_right_door_example.toml
@@ -2,9 +2,9 @@
Version = 100
[[Component]]
-Path = "doors_vd_reardoorright_rx.sdv"
+Path = "reardoors_vd_reardoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Right_Device"
[[Component]]
-Path = "doors_bs_reardoorright_rx.sdv"
+Path = "reardoors_bs_reardoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Right_Service"
diff --git a/examples/door_demo_example/door_app/console.cpp b/examples/door_demo_example/door_app/console.cpp
index acd9dea..f4c3cc2 100644
--- a/examples/door_demo_example/door_app/console.cpp
+++ b/examples/door_demo_example/door_app/console.cpp
@@ -128,7 +128,6 @@ void CConsole::PrintHeader(const uint32_t numberOfDoors)
PrintText(g_sTitle, title.c_str());
PrintText(g_sControlDescription, "Press 'X' to quit; Doors are toggled automatically");
}
-
}
bool CConsole::PrepareDataConsumers()
@@ -205,8 +204,7 @@ void CConsole::ResetSignals()
// Set the cursor position at the end
SetCursorPos(g_sCursor);
- // Registrate for the vehicle device & basic service of the front left door. Front left door mzust exist, the others are optional
- auto vehicleDevice =
+ auto vehicleDevice =
sdv::core::GetObject("Vehicle.Body.Door.Axle._01.Left_Device").GetInterface < vss::Vehicle::Body::Door::Axle::_01 ::LeftDevice::IVSS_ReadIsOpen > ();
if (vehicleDevice)
vehicleDevice->UnregisterIsOpenEvent(dynamic_cast (this));
@@ -254,7 +252,7 @@ void CConsole::StartUpdateDataThread()
m_bThreadStarted = true;
m_bRunning = true;
- m_threadReadTxSignals = std::thread(&CConsole::UpdateDataThreadFunc, this);
+ m_threadReadTxSignals = sdv::core::secure_thread(&CConsole::UpdateDataThreadFunc, this);
}
void CConsole::StopUpdateDataThread()
@@ -299,21 +297,21 @@ bool CConsole::PrepareDataConsumersForStandAlone()
{
// Subscribe for the door and if available get TX signal. Either both exists or none of them
sdv::core::CDispatchService dispatch;
- m_SignalFrontLeftDoorIsOpen = dispatch.Subscribe(doors::dsLeftDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontLeftDoorIsOpen(value); });
+ m_SignalFrontLeftDoorIsOpen = dispatch.Subscribe(frontdoors::dsLeftDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontLeftDoorIsOpen(value); });
if(m_SignalFrontLeftDoorIsOpen)
- m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
+ m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsLeftLatch01, 0);
- m_SignalFrontRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontRightDoorIsOpen(value); });
+ m_SignalFrontRightDoorIsOpen = dispatch.Subscribe(frontdoors::dsRightDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontRightDoorIsOpen(value); });
if(m_SignalFrontRightDoorIsOpen)
- m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
+ m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsRightLatch01, 0);
- m_SignalRearLeftDoorIsOpen = dispatch.Subscribe(doors::dsLeftDoorIsOpen02, [&](sdv::any_t value) {CallbackRearLeftDoorIsOpen(value); });
+ m_SignalRearLeftDoorIsOpen = dispatch.Subscribe(reardoors::dsLeftDoorIsOpen02, [&](sdv::any_t value) {CallbackRearLeftDoorIsOpen(value); });
if(m_SignalRearLeftDoorIsOpen)
- m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
+ m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsLeftLatch02, 0);
- m_SignalRearRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen02, [&](sdv::any_t value) { CallbackRearRightDoorIsOpen(value); });
+ m_SignalRearRightDoorIsOpen = dispatch.Subscribe(reardoors::dsRightDoorIsOpen02, [&](sdv::any_t value) { CallbackRearRightDoorIsOpen(value); });
if(m_SignalRearRightDoorIsOpen)
- m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
+ m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsRightLatch02, 0);
// Validate: Either both exists or none of them
if (m_SignalFrontLeftDoorIsOpen != m_SignalFrontLeftDoorIsLocked)
@@ -337,7 +335,7 @@ bool CConsole::PrepareDataConsumersForStandAlone()
return false;
}
- // Registrate for the vehicle device & basic service of the front left door. Front left door mzust exist, the others are optional
+ // Register for the vehicle device & basic service of the front left door. Front left door must exist, the others are optional
auto vehicleDevice = sdv::core::GetObject("Vehicle.Body.Door.Axle._01.Left_Device").GetInterface();
if (!vehicleDevice)
{
diff --git a/examples/door_demo_example/door_app/door_application.cpp b/examples/door_demo_example/door_app/door_application.cpp
index 1f0ee6a..4015879 100644
--- a/examples/door_demo_example/door_app/door_application.cpp
+++ b/examples/door_demo_example/door_app/door_application.cpp
@@ -9,7 +9,8 @@
********************************************************************************/
#include "../door_app/include/door_application.h"
-#include "../generated/vss_files/signal_identifier.h"
+#include "../generated/front/vss_files/signal_identifier.h"
+#include "../generated/rear/vss_files/signal_identifier.h"
#ifdef _WIN32
#include // Needed for _kbhit
@@ -61,23 +62,23 @@ bool CDoorControl::RegisterSignals()
{
sdv::core::CDispatchService dispatch;
- m_SignalFrontLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen01);
- m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
+ m_SignalFrontLeftDoorIsOpen = dispatch.RegisterRxSignal(frontdoors::dsLeftDoorIsOpen01);
+ m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsLeftLatch01, 0);
if (m_iNumberOfDoors > 1)
{
- m_SignalFrontRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen01);
- m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
+ m_SignalFrontRightDoorIsOpen = dispatch.RegisterRxSignal(frontdoors::dsRightDoorIsOpen01);
+ m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsRightLatch01, 0);
if (m_iNumberOfDoors > 2)
{
- m_SignalRearLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen02);
- m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
+ m_SignalRearLeftDoorIsOpen = dispatch.RegisterRxSignal(reardoors::dsLeftDoorIsOpen02);
+ m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsLeftLatch02, 0);
if (m_iNumberOfDoors > 3)
{
- m_SignalRearRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen02);
- m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
+ m_SignalRearRightDoorIsOpen = dispatch.RegisterRxSignal(reardoors::dsRightDoorIsOpen02);
+ m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsRightLatch02, 0);
}
}
}
diff --git a/examples/door_demo_example/door_app/door_extern_application.cpp b/examples/door_demo_example/door_app/door_extern_application.cpp
index 6cbdfbe..3189c1f 100644
--- a/examples/door_demo_example/door_app/door_extern_application.cpp
+++ b/examples/door_demo_example/door_app/door_extern_application.cpp
@@ -9,7 +9,8 @@
********************************************************************************/
#include "../door_app/include/door_extern_application.h"
-#include "../generated/vss_files/signal_identifier.h"
+#include "../generated/front/vss_files/signal_identifier.h"
+#include "../generated/rear/vss_files/signal_identifier.h"
#ifdef _WIN32
#include // Needed for _kbhit
diff --git a/examples/door_demo_example/door_app/include/console.h b/examples/door_demo_example/door_app/include/console.h
index b88e257..bfe2e92 100644
--- a/examples/door_demo_example/door_app/include/console.h
+++ b/examples/door_demo_example/door_app/include/console.h
@@ -19,15 +19,16 @@
#include
#include
#include
-#include "../../generated/vss_files/signal_identifier.h"
+#include "../../generated/front/vss_files/signal_identifier.h"
+#include "../../generated/rear/vss_files/signal_identifier.h"
#include
#include
-#include "../../generated/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.h"
-#include "../../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
-#include "../../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
-#include "../../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
-#include "../../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
+#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.h"
+#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
+#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
+#include "../../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
+#include "../../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
#ifdef __unix__
#include // Needed for tcgetattr and fcntl
@@ -215,41 +216,41 @@ private:
*/
std::string AlignString(const std::string& message, uint32_t desiredLength = 0);
- mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
- bool m_bThreadStarted = false; ///< Set when initialized.
- std::atomic_bool m_bRunning = false; ///< When set, the application is running.
- bool m_isExternalApp = false; ///< True when we have an external application
+ mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
+ bool m_bThreadStarted = false; ///< Set when initialized.
+ std::atomic_bool m_bRunning = false; ///< When set, the application is running.
+ bool m_isExternalApp = false; ///< True when we have an external application
- std::thread m_threadReadTxSignals; ///< Simulation datalink thread.
+ sdv::core::secure_thread m_threadReadTxSignals; ///< Simulation datalink thread.
- sdv::core::CSignal m_SignalFrontLeftDoorIsOpen; ///< Front Left Door signal (RX input) - open / closed
- sdv::core::CSignal m_SignalFrontRightDoorIsOpen; ///< Front Right Door signal (RX input) - open / closed
- sdv::core::CSignal m_SignalRearLeftDoorIsOpen; ///< Rear Left Door signal (RX input) - open / closed
- sdv::core::CSignal m_SignalRearRightDoorIsOpen; ///< Rear Right Door signal (RX input) - open / closed
+ sdv::core::CSignal m_SignalFrontLeftDoorIsOpen; ///< Front Left Door signal (RX input) - open / closed
+ sdv::core::CSignal m_SignalFrontRightDoorIsOpen; ///< Front Right Door signal (RX input) - open / closed
+ sdv::core::CSignal m_SignalRearLeftDoorIsOpen; ///< Rear Left Door signal (RX input) - open / closed
+ sdv::core::CSignal m_SignalRearRightDoorIsOpen; ///< Rear Right Door signal (RX input) - open / closed
- bool m_FrontLeftDoorIsOpen = false; ///< Front Left Door value (RX input signal) - open / closed
- bool m_FrontRightDoorIsOpen = false; ///< Front Right Door value (RX input signal) - open / closed
- bool m_RearLeftDoorIsOpen = false; ///< Rear Left Door value (RX input signal) - open / closed
- bool m_RearRightDoorIsOpen = false; ///< Rear Right Door value (RX input signal) - open / closed
+ bool m_FrontLeftDoorIsOpen = false; ///< Front Left Door value (RX input signal) - open / closed
+ bool m_FrontRightDoorIsOpen = false; ///< Front Right Door value (RX input signal) - open / closed
+ bool m_RearLeftDoorIsOpen = false; ///< Rear Left Door value (RX input signal) - open / closed
+ bool m_RearRightDoorIsOpen = false; ///< Rear Right Door value (RX input signal) - open / closed
- sdv::core::CSignal m_SignalFrontLeftDoorIsLocked; ///< Front Left Door signal (TX output) - locked / unlocked
- sdv::core::CSignal m_SignalFrontRightDoorIsLocked; ///< Front Right Door signal (TX output) - locked / unlocked
- sdv::core::CSignal m_SignalRearLeftDoorIsLocked; ///< Rear Left Door signal (TX output) - locked / unlocked
- sdv::core::CSignal m_SignalRearRightDoorIsLocked; ///< Rear Right Door signal (TX output) - locked / unlocked
+ sdv::core::CSignal m_SignalFrontLeftDoorIsLocked; ///< Front Left Door signal (TX output) - locked / unlocked
+ sdv::core::CSignal m_SignalFrontRightDoorIsLocked; ///< Front Right Door signal (TX output) - locked / unlocked
+ sdv::core::CSignal m_SignalRearLeftDoorIsLocked; ///< Rear Left Door signal (TX output) - locked / unlocked
+ sdv::core::CSignal m_SignalRearRightDoorIsLocked; ///< Rear Right Door signal (TX output) - locked / unlocked
- bool m_FrontLeftDoorIsLocked = false; ///< Front Left Door value (TX output) - locked / unlocked
- bool m_FrontRightDoorIsLocked = false; ///< Front Right Door value (TX output) - locked / unlocked
- bool m_RearLeftDoorIsLocked = false; ///< Rear Left Door value (TX output) - locked / unlocked
- bool m_RearRightDoorIsLocked = false; ///< Rear Right Door value (TX output) - locked / unlocked
+ bool m_FrontLeftDoorIsLocked = false; ///< Front Left Door value (TX output) - locked / unlocked
+ bool m_FrontRightDoorIsLocked = false; ///< Front Right Door value (TX output) - locked / unlocked
+ bool m_RearLeftDoorIsLocked = false; ///< Rear Left Door value (TX output) - locked / unlocked
+ bool m_RearRightDoorIsLocked = false; ///< Rear Right Door value (TX output) - locked / unlocked
- IDoorService* m_pDoorService = nullptr; ///< Door service interface pointer.
+ IDoorService* m_pDoorService = nullptr; ///< Door service interface pointer.
#ifdef _WIN32
- DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
- DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
+ DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
+ DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
#elif defined __unix__
- struct termios m_sTermAttr{}; ///< The terminal attributes before disabling echo.
- int m_iFileStatus = 0; ///< The file status flags for STDIN.
+ struct termios m_sTermAttr{}; ///< The terminal attributes before disabling echo.
+ int m_iFileStatus = 0; ///< The file status flags for STDIN.
#else
#error The OS is not supported!
#endif
diff --git a/examples/door_demo_example/door_service/complex_service.h b/examples/door_demo_example/door_service/complex_service.h
index c3b56fd..f25d963 100644
--- a/examples/door_demo_example/door_service/complex_service.h
+++ b/examples/door_demo_example/door_service/complex_service.h
@@ -19,14 +19,14 @@
#include
// VSS interfaces - located in ../generated/vss_files/
-#include "../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
-#include "../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.h"
+#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
+#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.h"
+#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
+#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.h"
+#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
+#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.h"
+#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
+#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.h"
#include "lock_doors_thread.h"
diff --git a/examples/door_demo_example/door_service/lock_doors_thread.h b/examples/door_demo_example/door_service/lock_doors_thread.h
index 510c138..0aa2cd3 100644
--- a/examples/door_demo_example/door_service/lock_doors_thread.h
+++ b/examples/door_demo_example/door_service/lock_doors_thread.h
@@ -40,7 +40,7 @@ public:
m_timeIn100MilliSeconds = timeSpan;
m_counter = 0;
m_running = true;
- m_thread = std::thread(&LockDoorsThread::run, this);
+ m_thread = sdv::core::secure_thread(&LockDoorsThread::run, this);
}
/**
@@ -94,11 +94,11 @@ public:
m_running = false;
}
- std::function m_callback; ///< callback function
- std::atomic m_running; ///< status if loop is running
- std::thread m_thread; ///< timer thread
- uint32_t m_counter; ///< loop counter
- uint32_t m_timeIn100MilliSeconds; ///< time before the callback will be executed
+ std::function m_callback; ///< callback function
+ std::atomic m_running; ///< status if loop is running
+ sdv::core::secure_thread m_thread; ///< timer thread
+ uint32_t m_counter; ///< loop counter
+ uint32_t m_timeIn100MilliSeconds; ///< time before the callback will be executed
};
#endif // !define LOCK_DOORS_THREAD_H
diff --git a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/model.cpp b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/model.cpp
index fa4b743..d77b2e3 100644
--- a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/model.cpp
+++ b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/model.cpp
@@ -100,7 +100,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
- tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
+ tomlFile << R"toml(# Location of the SDV binaries and configuration files
+[CoreLocation]
+Version = 100
+Framework = ")toml";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
diff --git a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_left_door_example.toml b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_left_door_example.toml
index 63c92da..e16120b 100644
--- a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_left_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_left_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorleft_rx.sdv"
+Path = "frontdoors_vd_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
[[Component]]
-Path = "doors_bs_frontdoorleft_rx.sdv"
+Path = "frontdoors_bs_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
diff --git a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_right_door_example.toml b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_right_door_example.toml
index 2aca0cd..05298a2 100644
--- a/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_right_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors2ExampleFMU/Doors2ExampleFMU/resources/front_right_door_example.toml
@@ -2,10 +2,10 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorright_rx.sdv"
+Path = "frontdoors_vd_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
[[Component]]
-Path = "doors_bs_frontdoorright_rx.sdv"
+Path = "frontdoors_bs_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
diff --git a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/model.cpp b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/model.cpp
index 7dd9d35..77892c7 100644
--- a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/model.cpp
+++ b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/model.cpp
@@ -125,7 +125,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
- tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
+ tomlFile << R"toml(# Location of the SDV binaries and configuration files
+[CoreLocation]
+Version = 100
+Framework = ")toml";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
diff --git a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_left_door_example.toml b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_left_door_example.toml
index e3162ea..142c14a 100644
--- a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_left_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_left_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorleft_rx.sdv"
+Path = "frontdoors_vd_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
[[Component]]
-Path = "doors_bs_frontdoorleft_rx.sdv"
+Path = "frontdoors_bs_frontdoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
diff --git a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_right_door_example.toml b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_right_door_example.toml
index 2aca0cd..05298a2 100644
--- a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_right_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/front_right_door_example.toml
@@ -2,10 +2,10 @@
Version = 100
[[Component]]
-Path = "doors_vd_frontdoorright_rx.sdv"
+Path = "frontdoors_vd_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
[[Component]]
-Path = "doors_bs_frontdoorright_rx.sdv"
+Path = "frontdoors_bs_frontdoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
diff --git a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_left_door_example.toml b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_left_door_example.toml
index 23e6935..b4a5871 100644
--- a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_left_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_left_door_example.toml
@@ -2,11 +2,11 @@
Version = 100
[[Component]]
-Path = "doors_vd_reardoorleft_rx.sdv"
+Path = "reardoors_vd_reardoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Left_Device"
[[Component]]
-Path = "doors_bs_reardoorleft_rx.sdv"
+Path = "reardoors_bs_reardoorleft_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Left_Service"
diff --git a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_right_door_example.toml b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_right_door_example.toml
index 4f2069e..64acf61 100644
--- a/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_right_door_example.toml
+++ b/examples/door_demo_example/fmu_Doors4ExampleFMU/Doors4ExampleFMU/resources/rear_right_door_example.toml
@@ -2,9 +2,9 @@
Version = 100
[[Component]]
-Path = "doors_vd_reardoorright_rx.sdv"
+Path = "reardoors_vd_reardoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Right_Device"
[[Component]]
-Path = "doors_bs_reardoorright_rx.sdv"
+Path = "reardoors_bs_reardoorright_rx.sdv"
Class = "Vehicle.Body.Door.Axle._02.Right_Service"
diff --git a/examples/door_demo_example/vss_doors_example.csv b/examples/door_demo_example/vss_doors_front_example.csv
similarity index 53%
rename from examples/door_demo_example/vss_doors_example.csv
rename to examples/door_demo_example/vss_doors_front_example.csv
index 005566f..f3e4e6e 100644
--- a/examples/door_demo_example/vss_doors_example.csv
+++ b/examples/door_demo_example/vss_doors_front_example.csv
@@ -2,17 +2,9 @@
;;;;;;;
VD;FrontDoorLeft;IsOpen;leftDoorIsOpen01;Vehicle.Body.Door.Axle.01.Left;RX;boolean;CAN_Input_L1.Door01LeftIsOpen
VD;FrontDoorRight;IsOpen;rightDoorIsOpen01;Vehicle.Body.Door.Axle.01.Right;RX;boolean;CAN_Input_R1.Door01RightIsOpen
-VD;RearDoorLeft;IsOpen;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;CAN_Input_L2.Door02LeftIsOpen
-VD;RearDoorRight;IsOpen;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;CAN_Input_R2.Door02RightIsOpen
VD;FrontDoorLeft;Lock;leftLatch01;Vehicle.Body.Door.Axle.01.Left;TX;boolean;CAN_Output.LockDoor01Left
VD;FrontDoorRight;Lock;rightLatch01;Vehicle.Body.Door.Axle.01.Right;TX;boolean;CAN_Output.LockDoor01Right
-VD;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;CAN_Output.LockDoor02Left
-VD;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;CAN_Output.LockDoor02Right
BS;FrontDoorLeft;IsOpenL1;leftDoorIsOpen01;Vehicle.Body.Door.Axle.01.Left;RX;boolean;Vehicle.Body.Door.Axle.01.Left
BS;FrontDoorRight;IsOpenR1;rightDoorIsOpen01;Vehicle.Body.Door.Axle.01.Right;RX;boolean;Vehicle.Body.Door.Axle.01.Right
-BS;RearDoorLeft;IsOpenL2;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;Vehicle.Body.Door.Axle.02.Left
-BS;RearDoorRight;IsOpenR2;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;Vehicle.Body.Door.Axle.02.Right
BS;FrontDoorLeft;Lock;leftLatch01;Vehicle.Body.Door.Axle.01.Left;TX;boolean;Vehicle.Body.Door.Axle.01.Left
BS;FrontDoorRight;Lock;rightLatch01;Vehicle.Body.Door.Axle.01.Right;TX;boolean;Vehicle.Body.Door.Axle.01.Right
-BS;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;Vehicle.Body.Door.Axle.02.Left
-BS;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;Vehicle.Body.Door.Axle.02.Right
diff --git a/examples/door_demo_example/vss_doors_rear_example.csv b/examples/door_demo_example/vss_doors_rear_example.csv
new file mode 100644
index 0000000..285c0e5
--- /dev/null
+++ b/examples/door_demo_example/vss_doors_rear_example.csv
@@ -0,0 +1,10 @@
+;Class name;Function name;Signal name;vss;Signal direction;type;DBC CAN name includes CAN message name
+;;;;;;;
+VD;RearDoorLeft;IsOpen;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;CAN_Input_L2.Door02LeftIsOpen
+VD;RearDoorRight;IsOpen;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;CAN_Input_R2.Door02RightIsOpen
+VD;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;CAN_Output.LockDoor02Left
+VD;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;CAN_Output.LockDoor02Right
+BS;RearDoorLeft;IsOpenL2;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;Vehicle.Body.Door.Axle.02.Left
+BS;RearDoorRight;IsOpenR2;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;Vehicle.Body.Door.Axle.02.Right
+BS;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;Vehicle.Body.Door.Axle.02.Left
+BS;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;Vehicle.Body.Door.Axle.02.Right
diff --git a/examples/open_trunk_example/open_trunk_app/console.cpp b/examples/open_trunk_example/open_trunk_app/console.cpp
index 1975242..612318b 100644
--- a/examples/open_trunk_example/open_trunk_app/console.cpp
+++ b/examples/open_trunk_example/open_trunk_app/console.cpp
@@ -34,9 +34,11 @@ const CConsole::SConsolePos g_sComment3{ 24, 1 };
const CConsole::SConsolePos g_sSeparator5{ 26, 1 };
const CConsole::SConsolePos g_sOpenViaDevice{ 28, 1 };
const CConsole::SConsolePos g_sOpenViaService{ 29, 1 };
-const CConsole::SConsolePos g_sSeparator6{ 31, 1 };
-const CConsole::SConsolePos g_sControlDescription{ 33, 1 };
-const CConsole::SConsolePos g_sCursor{ 34, 1 };
+const CConsole::SConsolePos g_sAutoCloseTrunk{ 30, 1 };
+const CConsole::SConsolePos g_sStatusTrunk{ 32, 1 };
+const CConsole::SConsolePos g_sSeparator6{ 34, 1 };
+const CConsole::SConsolePos g_sControlDescription{ 36, 1 };
+const CConsole::SConsolePos g_sCursor{ 37, 1 };
CConsole::CConsole()
{
@@ -92,6 +94,7 @@ void CConsole::PrintHeader(uint32_t uiInstance)
{
subTtitle = "Connected to core instance ";
subTtitle.append(std::to_string(uiInstance));
+ subTtitle.append(" (not all interfaces available)");
}
// Print the titles
PrintText(g_sTitle, "Open Trunk example: Open trunk when vehicle is not moving");
@@ -108,7 +111,7 @@ void CConsole::PrintHeader(uint32_t uiInstance)
PrintText(g_sSeparator4, "============================================================================");
PrintText(g_sComment1, "The Open Trunk signal has a safety request.");
PrintText(g_sComment2, "Therefore the speed value is required and must be checked.");
- PrintText(g_sComment3, "If the car is moving, open is blocked and trunk is closed automatically.");
+ PrintText(g_sComment3, "If the vehicle is moving, open is blocked and trunk is closed automatically.");
PrintText(g_sSeparator5, "============================================================================");
PrintText(g_sOpenViaDevice, "Vehicle Device Interface not available.");
PrintText(g_sOpenViaService, "Basic Service Interface not available.");
@@ -124,7 +127,7 @@ bool CConsole::PrepareDataConsumers()
if (m_SignalSpeed)
PrintValue(g_sDataLinkSpeed, "Vehicle Speed RX", m_SpeedDL, "m/s");
- // Registrate for the vehicle device & basic service of the speed.
+ // Register for the vehicle device & basic service of the speed.
auto vehicleDevice = sdv::core::GetObject("Vehicle.Speed_Device").GetInterface();
if (vehicleDevice)
{
@@ -153,6 +156,10 @@ bool CConsole::PrepareDataConsumers()
else
PrintText(g_sOpenViaDevice, "Trunk Device NOT available");
+ m_SignalStatusTrunk = dispatch.RegisterTxSignal(trunk::dsTrunk, 0);
+ if (!m_SignalStatusTrunk)
+ PrintText(g_sStatusTrunk, "Trunk Status not available.");
+
return true;
}
@@ -172,6 +179,9 @@ void CConsole::ResetSignals()
// Unregister the data link signals
if (m_SignalSpeed)
m_SignalSpeed.Reset();
+
+ if (m_SignalStatusTrunk)
+ m_SignalStatusTrunk.Reset();
}
void CConsole::CallbackSpeed(sdv::any_t value)
@@ -246,7 +256,13 @@ void CConsole::SetSpeed(float value)
if (bIsMoving && !m_bWasMovingBS)
{
- PrintText(g_sOpenViaService, "Safety active: speed > 0, trunk close command sent.");
+ if (m_pTrunkService)
+ {
+ if (m_pTrunkService->SetOpen(false))
+ PrintText(g_sAutoCloseTrunk, "Safety feature active: Trunk closed as the vehicle started moving.");
+ else
+ PrintText(g_sOpenViaService, "Close trunk automatically failed.");
+ }
}
m_bWasMovingBS = bIsMoving;
}
@@ -278,9 +294,24 @@ char CConsole::GetChar()
void CConsole::RunUntilBreak()
{
bool bRunning = true;
+ bool bTrunkClosed = true;
while (bRunning)
{
+ if(m_SignalStatusTrunk)
+ {
+ auto value =m_SignalStatusTrunk.Read().get();
+ if (bTrunkClosed != value)
+ {
+ bTrunkClosed = value;
+ if (bTrunkClosed)
+ PrintText(g_sStatusTrunk, "Status: Trunk is open.");
+ else
+ PrintText(g_sStatusTrunk, "Status: Trunk is closed.");
+ }
+ }
+
+
// Check for a key
if (!KeyHit())
{
@@ -294,17 +325,19 @@ void CConsole::RunUntilBreak()
{
case 'c':
case 'C':
- PrintText(g_sOpenViaDevice, " ");
- PrintText(g_sOpenViaService, " ");
+ PrintText(g_sOpenViaDevice, " ");
+ PrintText(g_sOpenViaService, " ");
+ PrintText(g_sAutoCloseTrunk, " ");
break;
case 'd':
case 'D':
if (m_pTrunkDevice)
{
+ PrintText(g_sAutoCloseTrunk, " ");
if (m_pTrunkDevice->WriteOpen(true))
{
if (m_SpeedVD || m_SpeedBS)
- PrintText(g_sOpenViaDevice, "Trunk opened directly although car was moving, not safe.");
+ PrintText(g_sOpenViaDevice, "Trunk opened directly although vehicle was moving, not safe.");
else
PrintText(g_sOpenViaDevice, "Trunk opened directly, not safe.");
}
@@ -316,10 +349,11 @@ void CConsole::RunUntilBreak()
case 'O':
if (m_pTrunkService)
{
+ PrintText(g_sAutoCloseTrunk, " ");
if (m_pTrunkService->SetOpen(true))
PrintText(g_sOpenViaService, "Trunk opened safely (auto-close if vehicle starts moving).");
else
- PrintText(g_sOpenViaService, "Open trunk failed, car is moving.");
+ PrintText(g_sOpenViaService, "Open trunk failed, vehicle is moving.");
}
break;
case 'x':
diff --git a/examples/open_trunk_example/open_trunk_app/console.h b/examples/open_trunk_example/open_trunk_app/console.h
index 326e833..0ce6338 100644
--- a/examples/open_trunk_example/open_trunk_app/console.h
+++ b/examples/open_trunk_example/open_trunk_app/console.h
@@ -157,6 +157,7 @@ private:
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
bool m_bRunning = false; ///< When set, the application is running.
+ sdv::core::CSignal m_SignalStatusTrunk; ///< Status of the trunk, only available in the standalone example
sdv::core::CSignal m_SignalSpeed; ///< Speed
float m_SpeedDL = 0.0; ///< Speed Data Link
float m_SpeedVD = 0.0; ///< Speed Vehicle Device
diff --git a/examples/system_demo_example/example_app/console.cpp b/examples/system_demo_example/example_app/console.cpp
index f9b588e..114ec69 100644
--- a/examples/system_demo_example/example_app/console.cpp
+++ b/examples/system_demo_example/example_app/console.cpp
@@ -209,8 +209,7 @@ bool CConsole::PrepareDataConsumers()
m_pCounterSteeringSvc = sdv::core::GetObject("Counter Steering Example Service").GetInterface();
if (!m_pCounterSteeringSvc)
{
- std::cerr << "Console ERROR: Could not get complex service interface 'ICounterSteeringService'" << std::endl;
- return false;
+ PrintText(g_sCSActive, "Attention: Complex service 'CounterSteeringService' is not available.");
}
return true;
diff --git a/examples/system_demo_example/example_app/control.cpp b/examples/system_demo_example/example_app/control.cpp
index 5090b88..3eac499 100644
--- a/examples/system_demo_example/example_app/control.cpp
+++ b/examples/system_demo_example/example_app/control.cpp
@@ -103,7 +103,7 @@ void CExampleControl::StartTestRun()
// Start the simulated datalink
m_bRunning = true;
- m_threadSimulateDatalink = std::thread(&CExampleControl::SimulateDatalinkThreadFunc, this);
+ m_threadSimulateDatalink = sdv::core::secure_thread(&CExampleControl::SimulateDatalinkThreadFunc, this);
}
void CExampleControl::StopTestRun()
diff --git a/examples/system_demo_example/example_app/control.h b/examples/system_demo_example/example_app/control.h
index c6d8e7e..5a343f6 100644
--- a/examples/system_demo_example/example_app/control.h
+++ b/examples/system_demo_example/example_app/control.h
@@ -163,20 +163,20 @@ private:
verbose, ///< Extensive reporting by application control
};
- bool m_bInitialized = false; ///< Set when initialized.
- bool m_bCmdLnError = false; ///< Command line error occurred.
- bool m_bCmdLnHelp = false; ///< Command line help provided.
- std::atomic_bool m_bRunning = false; ///< When set, the application is running.
- ERunAs m_eRunAs = ERunAs::standalone; ///< Application operation.
- EAppControlReporting m_eReporting = EAppControlReporting::silent; ///< Application control reporting.
- uint32_t m_uiInstance = 1000u; ///< Server instance to connect to.
- std::filesystem::path m_pathFramework; ///< Path to the SDV V-API framework.
- sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
- std::thread m_threadSimulateDatalink; ///< Simulation datalink thread.
- sdv::core::CSignal m_signalSteeringWheel; ///< Steering wheel angle signal (input) - simulated datalink
- sdv::core::CSignal m_signalSpeed; ///< Speed signal (input) - simulated datalink
- sdv::core::CSignal m_signalRearAngle; ///< Rear angle signal (output) - simulated datalink
- sdv::core::CSignal m_signalCounter; ///< Simple counter signal (output) - simulated datalink
+ bool m_bInitialized = false; ///< Set when initialized.
+ bool m_bCmdLnError = false; ///< Command line error occurred.
+ bool m_bCmdLnHelp = false; ///< Command line help provided.
+ std::atomic_bool m_bRunning = false; ///< When set, the application is running.
+ ERunAs m_eRunAs = ERunAs::standalone; ///< Application operation.
+ EAppControlReporting m_eReporting = EAppControlReporting::silent; ///< Application control reporting.
+ uint32_t m_uiInstance = 1000u; ///< Server instance to connect to.
+ std::filesystem::path m_pathFramework; ///< Path to the SDV V-API framework.
+ sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
+ sdv::core::secure_thread m_threadSimulateDatalink; ///< Simulation datalink thread.
+ sdv::core::CSignal m_signalSteeringWheel; ///< Steering wheel angle signal (input) - simulated datalink
+ sdv::core::CSignal m_signalSpeed; ///< Speed signal (input) - simulated datalink
+ sdv::core::CSignal m_signalRearAngle; ///< Rear angle signal (output) - simulated datalink
+ sdv::core::CSignal m_signalCounter; ///< Simple counter signal (output) - simulated datalink
};
template
diff --git a/examples/system_demo_example/fmu/model.cpp b/examples/system_demo_example/fmu/model.cpp
index 3983302..c75a484 100644
--- a/examples/system_demo_example/fmu/model.cpp
+++ b/examples/system_demo_example/fmu/model.cpp
@@ -103,7 +103,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
- tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
+ tomlFile << R"toml(# Location of the SDV binaries and configuration files
+[CoreLocation]
+Version = 100
+Framework = ")toml";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
diff --git a/export/interfaces/app.idl b/export/interfaces/app.idl
index 4efcaff..5357769 100644
--- a/export/interfaces/app.idl
+++ b/export/interfaces/app.idl
@@ -103,12 +103,6 @@ module sdv
* @return The instance ID.
*/
uint32 GetInstanceID() const;
-
- /**
- * @brief Return the number of retries to establish a connection.
- * @return Number of retries.
- */
- uint32 GetRetries() const;
};
/**
@@ -181,5 +175,96 @@ module sdv
void RequestShutdown() raises(XAccessDenied, XInvalidState);
};
+ /**
+ * @brief Load and save the application settings.
+ * @remarks The interface is only available in maintenance mode.
+ */
+ interface IAppSettingsPersist
+ {
+ /**
+ * @brief Load the application settings.
+ * @remarks When there is no settings file, this is not an error. Default settings will be assumed.
+ * @return Returns whether the loading was successful.
+ */
+ boolean LoadSettings();
+
+ /**
+ * @brief Save the application settings file (or create when not existing yet).
+ * @return Returns whether the saving was successful.
+ */
+ boolean SaveSettings();
+ };
+
+ /**
+ * @brief Application connections
+ * @remarks The interface is only available in maintenance mode.
+ */
+ interface IAppConnections
+ {
+ /**
+ * @brief Get a sequence with listener names.
+ * @return Sequence with listener name strings.
+ */
+ sequence GetListeners() const;
+
+ /**
+ * @brief Get the listener configuration.
+ * @param[in] ssName Name of the listener.
+ * @return String containing the listener configuration.
+ */
+ u8string GetListenerConfig(in u8string ssName) const;
+
+ /**
+ * @brief Add or update a listener configuration.
+ * @param[in] ssName Name of the listener configuration.
+ * @param[in] ssConfig The configuration string for the listener.
+ * @return Returns whether the listener could be added.
+ */
+ boolean AddListenerConfig(in u8string ssName, in u8string ssConfig);
+
+ /**
+ * @brief Remove a listener configuration with the provided name.
+ * @param[in] ssName Name of the listener configuration.
+ * @return Returns whether the removal was successful.
+ */
+ boolean RemoveListenerConfig(in u8string ssName);
+
+ /**
+ * @brief Get a sequence with connection names.
+ * @return Sequence with name strings.
+ */
+ sequence GetConnections() const;
+
+ /**
+ * @brief Get the connection configuration.
+ * @param[in] ssName Name of the connection.
+ * @return String containing the connection configuration.
+ */
+ u8string GetConnectionConfig(in u8string ssName) const;
+
+ /**
+ * @brief Add or update a connection configuration.
+ * @param[in] ssName Name of the connection configuration.
+ * @param[in] ssConfig The configuration string for the connection.
+ * @param[in] ssInsertBefore Reference to the string to connection to insert the the new connection before, or empty
+ * when the the new connection should be placed at the end.
+ * @return Returns whether the connection could be added (fails when the connection already exists).
+ */
+ boolean AddConnectionConfig(in u8string ssName, in u8string ssConfig, in u8string ssInsertBefore);
+
+ /**
+ * @brief Remove a connection configuration with the provided name.
+ * @param[in] ssName Name of the connection configuration.
+ * @return Returns whether the removal was successful.
+ */
+ boolean RemoveConnectionConfig(in u8string ssName);
+
+ /**
+ * @brief Return the number of retries to establish a connection.
+ * @return Number of retries.
+ */
+ uint32 GetConnectRetries() const;
+ };
+
}; // module app
}; // module sdv
diff --git a/export/interfaces/com.idl b/export/interfaces/com.idl
index 2f2d392..e82fcd8 100644
--- a/export/interfaces/com.idl
+++ b/export/interfaces/com.idl
@@ -53,31 +53,56 @@ module sdv
};
/**
- * @brief Connect to a remote system. Provided by the ConnectClient utility.
+ * @brief Connect to a remote system. Provided by the Connection service.
+ * @details This interface is exposed by the connection client service. The configuration is provided during instantiation
+ * of the object and is of the form:
+ * @code
+ * # Provider to use for the connection
+ * [Provider]
+ * Name = ""
+ *
+ * # Additional channel information for the client
+ * [IpcChannel]
+ * xyz = ""
+ * @endcode
+ *
+ * For example for shared memory:
+ * @code
+ * [Provider]
+ * Name = "DefaultSharedMemory"
+ * [IpcChannel]
+ * Name = "LISTENER_1234"
+ * @endcode
*/
interface IClientConnect
{
/**
- * @brief Connect to a remote system using the connection string to contact the system.
- * @remarks After a successful connection, the ConnectClient utility is not needed any more.
- * @param[in] ssConnectString Optional connection string to use for connection. If not provided, the connection will
- * automatically get the connection ID from the app-control service (default). The connection string for a local
- * connection can be of the form:
- * @code
- * [Client]
- * Type = "local"
- * Instance = 1234 # Optional: only use when connecting to a system with a different instance ID.
- * @endcode
- * And the following can be used for a remote connection:
- * @code
- * [Client]
- * Type = "remote"
- * Interface = "127.0.0.1"
- * Port = 2000
- * @endcode
- * @return Returns an interface to the repository of the remote system or a NULL pointer if not found.
+ * @brief Connect to a remote system.
+ * @return Returns whether connect was successful.
*/
- IInterfaceAccess Connect(in u8string ssConnectString) raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
+ boolean Connect() raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
+
+ /**
+ * @brief Disconnect from a connected system.
+ * @return Returns whether disconnect was successful.
+ */
+ boolean Disconnect() raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
+
+ /**
+ * @brief State of the current connection.
+ * @return Returns whether an active connection exists.
+ */
+ boolean IsConnected() const;
+
+ /**
+ * @brief Get the remote repository that is available after connection.
+ * @remarks For main, isolated and external applications, the remote repository will be automatically linked to the
+ * local repository. Hence a requests for the repository is not needed. For all other applications, access must be
+ * explicitly acquired through this interface.
+ * @return Interface to the remote repository if a successful connection is established. The interface is valid until
+ * disconnect is called or the client connection service is terminated.
+ */
+ IInterfaceAccess GetRemoteRepository();
};
/**
diff --git a/export/interfaces/config.idl b/export/interfaces/config.idl
index a598df2..6c44b9f 100644
--- a/export/interfaces/config.idl
+++ b/export/interfaces/config.idl
@@ -389,6 +389,17 @@ module sdv
u8string ssInstallName; ///< Name of the installation.
};
+ /**
+ * @brief The package exceeds the maximum size.
+ */
+ exception XPackageSizeExceeded : XSysExcept
+ {
+ /** Description */
+ const char _description[] = "Maximum package size exceeded.";
+
+ u8string ssFileName; ///< Name of the file which causes the exception.
+ };
+
/**
* @brief The installation doesn't contain a module.
*/
diff --git a/export/interfaces/core.idl b/export/interfaces/core.idl
index 3685736..d537a35 100644
--- a/export/interfaces/core.idl
+++ b/export/interfaces/core.idl
@@ -57,11 +57,28 @@ module sdv
template
TInterface* GetInterface()
{
- return GetInterface(sdv::GetInterfaceId()).template get();
+ try
+ {
+ return GetInterface(sdv::GetInterfaceId()).template get();
+ } catch (const XSysExcept&)
+ {
+ return nullptr;
+ }
}
#verbatim_end
};
+ /**
+ * @brief Core features.
+ */
+ module core
+ {
+ /**
+ * @brief Object ID.
+ */
+ typedef uint64 TObjectID;
+ };
+
/**
* @brief Object type enumeration.
*/
@@ -163,13 +180,24 @@ module sdv
/**
* @brief Component operation mode.
- */
+ */
enum EOperationMode : uint32
{
configuring = 20, ///< The component should switch to configuration mode.
running = 30, ///< The component should switch to running mode.
};
+ /**
+ * @brief Object information supplied to the object initialization function.
+ */
+ struct SObjectInfo
+ {
+ core::TObjectID tObjectID; ///< Object ID (local for the running process)
+ SClassInfo sClassInfo; ///< Object class information
+ u8string ssName; ///< Object name
+ u8string ssConfig; ///< Object configuration TOML
+ };
+
/**
* @brief Optional interface allowing for additional control of more complex SDVObjects.
* To be implemented if the object in question calls other SDVobjects via running threads or callbacks,
@@ -179,9 +207,9 @@ module sdv
{
/**
* @brief Initialize the object.
- * @param[in] ssObjectConfig Optional configuration string.
+ * @param[in] sObjectInfo The registration information of this object.
*/
- void Initialize(in u8string ssObjectConfig);
+ void Initialize(in SObjectInfo sObjectInfo);
/**
* @brief Get the current state of the object.
@@ -247,50 +275,6 @@ module sdv
*/
uint32 GetCount() const;
};
-
- /**
- * @brief Attribute flags.
- */
- enum EAttributeFlags : uint32
- {
- read_only = 0x100, ///< When set, the attribute is readonly.
- };
-
- /**
- * @brief Attribute interface
- */
- interface IAttributes
- {
- /**
- * @brief Get a sequence with the available attribute names.
- * @return The sequence of attribute names.
- */
- sequence GetNames() const;
-
- /**
- * @brief Get the attribute value.
- * @param[in] ssAttribute Name of the attribute.
- * @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
- */
- any Get(in u8string ssAttribute) const;
-
- /**
- * @brief Set the attribute value.
- * @param[in] ssAttribute Name of the attribute.
- * @param[in] anyAttribute Attribute value to set.
- * @return Returns 'true' when setting the attribute was successful or 'false' when the attribute was not found or the
- * attribute is read-only or another error occurred.
- */
- boolean Set(in u8string ssAttribute, in any anyAttribute);
-
- /**
- * @brief Get the attribute flags belonging to a certain attribute.
- * @param[in] ssAttribute Name of the attribute.
- * @return Returns the attribute flags (zero or more EAttributeFlags flags) or 0 when the attribute could not be found.
- */
- uint32 GetFlags(in u8string ssAttribute) const;
- };
-
}; // module sdv
#verbatim_begin
diff --git a/export/interfaces/core_ps.idl b/export/interfaces/core_ps.idl
index 04d4df3..c72a873 100644
--- a/export/interfaces/core_ps.idl
+++ b/export/interfaces/core_ps.idl
@@ -13,6 +13,7 @@
#include "core.idl"
#include "process.idl"
+#include "permission.idl"
/**
* @brief Software Defined Vehicle framework.
@@ -149,6 +150,7 @@ module sdv
TMarshallID tProxyID; ///< Proxy id to identify the proxy this packet is sending from or destined to.
TMarshallID tStubID; ///< Stub id to identify the stub this packet is destined to or receiving from.
uint64 uiCallIndex; ///< Call index to uniquely identify the call.
+ core::TPermissionID tPermissionID; ///< Permission ID used to elevate permission, or 0 for standard permission.
};
/**
diff --git a/export/interfaces/ipc.idl b/export/interfaces/ipc.idl
index 75cd4a6..ab623c0 100644
--- a/export/interfaces/ipc.idl
+++ b/export/interfaces/ipc.idl
@@ -35,12 +35,15 @@ module sdv
///< identification must be similar to the following example:
///< @code
///< [Provider]
- ///< Name = "DefaultSharedMemoryChannelControl"
+ ///< Name = "DefaultSharedMemory"
///< @endcode
};
/**
- * @brief Interface for creating an IPC connection, which other participants can connect to via IChannelAccess
+ * @brief Interface for creating an IPC connection, which other participants can connect to via IChannelAccess.
+ * @attention The channel control object should allow the creation of channels with a fixed configuration (e.g. a provided
+ * name or a port), which is necessary for the creation of a listener. It also should allow dynamic channel creation (e.g.
+ * automatic name or port-number) to create additional connections between components.
*/
interface ICreateEndpoint
{
diff --git a/export/interfaces/permission.idl b/export/interfaces/permission.idl
new file mode 100644
index 0000000..f1a3fa3
--- /dev/null
+++ b/export/interfaces/permission.idl
@@ -0,0 +1,96 @@
+/********************************************************************************
+ * Copyright (c) 2025-2026 ZF Friedrichshafen AG
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Apache License Version 2.0 which is available at
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Contributors:
+ * Erik Verhoeven - initial API and implementation
+ ********************************************************************************/
+
+#include "core.idl"
+
+/**
+ * @brief Software Defined Vehicle framework.
+ */
+module sdv
+{
+ /**
+ * @brief Core features.
+ */
+ module core
+ {
+ /// ID corresponding to a thread specific permission request.
+ typedef uint64 TPermissionID;
+
+ /// ID identifying a permission transfer.
+ typedef uint64 TPermissionTransferID;
+
+ /**
+ * @brief Access type restriction. The lower the access, the more restricted.
+ */
+ enum EAccessPermission : int32
+ {
+ not_set = -1001, ///< Permissions are not set; will be treated as restricted access.
+ restricted_access = -1000, ///< Restricted access (default when no other set).
+ remote_access = -200, ///< Access for remote execution. Access allowed to basic and complex services.
+ local_access = -100, ///< Access for isolated execution. Access allowed to system, basic and complex services.
+ full_access = 0, ///< Full access is allowed to complete system.
+ };
+
+ /**
+ * @brief Permission control interface. This interface is used for restricting permission on a thread and transferring
+ * permissions from one thread to another.
+ */
+ interface IPermissionControl
+ {
+ /**
+ * @brief Restrict the access permission for the current thread.
+ * @remarks The access restriction will be assigned to the current thread and combined with previous and future
+ * permissions. The lowest assigned permission will determine the actual access permission for the current thread.
+ * @remarks The access restriction will stay in effect until it is released by the function ReleaseAccessPermission.
+ * @remarks A newly created thread has fully restricted access. This cannot be changed using this function. Use an
+ * access restriction transfer from one thread to this thread to set a higher level of access permission.
+ * @param[in] ePermission The permission to restrict to.
+ * @return The permission ID for this restriction or 0 when the access permission could not be set. Use the
+ * ReleaseAccessPermission to release the restriction again.
+ */
+ TPermissionID RestrictAccessPermission(in EAccessPermission ePermission);
+
+ /**
+ * @brief Release a previously set access restriction for the current thread.
+ * @param[in] tPermissionID The ID of the access restriction previously set for the current thread.
+ * @return Returns whether the restriction could be released successfully.
+ */
+ boolean ReleaseAccessPermission(in TPermissionID tPermissionID);
+
+ /**
+ * @brief Prepares a transfer of the access restriction from the current thread.
+ * @return The ID of the transfer object containing the current access permissions or 0 when the transfer preparation
+ * has failed.
+ */
+ TPermissionTransferID TransferCurrentPermission();
+
+ /**
+ * @brief Set the access permission using a transfer object from one thread to another.
+ * @remarks An new thread has fully restricted access per default. Use this function to set the required access level.
+ * If a thread has already initialized with the proper access level, this function will set identical or lower access
+ * permissions for the current thread.
+ * @param[in] tTransferID The IS of the prepared access permission transfer.
+ * @return The permission ID for this restriction or 0 when the access permission could not be transferred. Use the
+ * ReleaseAccessPermission to release the restriction again.
+ */
+ TPermissionID SetAccessPermission(in TPermissionTransferID tTransferID);
+
+ /**
+ * @brief Get the access permission level for the current thread. This will be the lowest restriction set for the
+ * current thread.
+ * @return The current access permission level.
+ */
+ EAccessPermission GetCurrentPermission() const;
+ };
+ }; // module core
+}; // module sdv
diff --git a/export/interfaces/repository.idl b/export/interfaces/repository.idl
index 6965a02..527293a 100644
--- a/export/interfaces/repository.idl
+++ b/export/interfaces/repository.idl
@@ -25,11 +25,6 @@ module sdv
module core
{
- /**
- * @brief Object ID.
- */
- typedef uint64 TObjectID;
-
/**
* @brief Interface used to access objects from other modules via the repository service
*/
@@ -229,6 +224,32 @@ module sdv
TObjectID RegisterObject(in IInterfaceAccess pObjectIfc, in u8string ssObjectName);
};
+ /**
+ * @brief The object dependency can be used to state dependencies between two objects. This influence is used during
+ * shutdown to determine the termination order.
+ */
+ interface IObjectDependency
+ {
+ /**
+ * @brief Add a dependency for an object.
+ * @param ssObjectName Name of the object.
+ * @param ssDependsOnObject Name of the object it depends on.
+ */
+ void AddObjectDependency(in u8string ssObjectName, in u8string ssDependsOnObject);
+
+ /**
+ * @brief Remove an object dependency.
+ * @param ssObjectName Name of the object.
+ * @param ssDependsOnObject Name of the object it depends on.
+ */
+ void RemoveObjectDependency(in u8string ssObjectName, in u8string ssDependsOnObject);
+ };
+
+ /**
+ * @brief Link ID.
+ */
+ typedef uint64 TLinkID;
+
/**
* @brief Connect the core repository to the local repository to allow object access by the locally running components.
* @remarks This interface is available only for isolated and external applications.
@@ -238,13 +259,15 @@ module sdv
/**
* @brief Register the core repository.
* @param[in] pCoreRepository Pointer to the proxy interface of the core repository.
+ * @return Returns a link ID to be used in the Unlink function. Or 0 on failure.
*/
- void LinkCoreRepository(in IInterfaceAccess pCoreRepository);
+ TLinkID LinkCoreRepository(in IInterfaceAccess pCoreRepository);
/**
* @brief Unlink a previously linked core repository.
+ * @param[in] tLinkID Link ID of the repository link to remove.
*/
- void UnlinkCoreRepository();
+ void UnlinkCoreRepository(in TLinkID tLinkID);
};
}; // module core
diff --git a/export/interfaces/toml.idl b/export/interfaces/toml.idl
index 0f94af6..98d6852 100644
--- a/export/interfaces/toml.idl
+++ b/export/interfaces/toml.idl
@@ -142,10 +142,10 @@ module sdv
u8string GetComment(in ECommentType eType);
/**
- * @brief Format the node automatically. This will remove the whitespace between the elements within the node. Comments
- * will not be changed.
+ * @brief Format the node automatically, remove redundant whitespace.
+ * @param[in] bRemoveComments When set, the comments are removed from the node.
*/
- void AutomaticFormat();
+ void AutomaticFormat(in boolean bRemoveComments);
/**
* @brief Is the node inline?
@@ -265,10 +265,21 @@ module sdv
/**
* @brief Convert the node to a standard node.
+ * @param[in] bIncludeChildren When set, applicable child nodes are made are converted to standard nodes as well (only
+ * tables and table-arrays can be defined as standard).
* @return Returns whether the conversion was successful. Returns 'true' when the node was already defined as standard
* node.
*/
- boolean MakeStandard();
+ boolean MakeStandard(in boolean bIncludeChildren);
+ };
+
+ /**
+ * @brief Insertion preference for tables and table arrays, being standard or inline.
+ */
+ enum EInsertPreference
+ {
+ prefer_standard = 0, ///< When the parent node is not inline, the node will be inserted as standard node.
+ prefer_inline = 1, ///< The node will be inserted as inline node.
};
/**
@@ -278,71 +289,67 @@ module sdv
{
/**
* @brief Insert a value into the collection at the location before the supplied index.
- * @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
- * collection count to insert the node at the end of the collection. Value nodes cannot be inserted behind external
- * tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
- * is automatically corrected.
- * @param[in] ssName Name of the node to insert. Will be ignored for an array collection. The name must adhere to the
- * key names defined by the TOML specification. Defining the key multiple times is not allowed. Quotation of key names
- * is done automatically; the parser decides itself whether the key is bare-key, a literal key or a quoted key.
+ * @remarks In TOML, inline nodes are located before standard nodes. Since values are presented as inline node, they
+ * will be inserted before any standard node (table or table array if defined as standard node).
+ * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
+ * square brackets. Can be empty, causing the node to be inserted at the end.
+ * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
+ * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
+ * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
+ * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
+ * parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] anyValue The value of the node, being either an integer, floating point number, boolean value or a string.
* Conversion is automatically done to int64, double float, bool or u8string.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
- IInterfaceAccess InsertValue(in uint32 uiIndex, in u8string ssName, in any anyValue);
+ IInterfaceAccess InsertValue(in u8string ssInsertBefore, in u8string ssName, in any anyValue);
/**
* @brief Insert an array into the collection at the location before the supplied index.
- * @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
- * collection count to insert the node at the end of the collection. Array nodes cannot be inserted behind external
- * tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
- * is automatically corrected.
- * @param[in] ssName Name of the array node to insert. Will be ignored if the current node is also an array collection.
- * The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
- * allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
- * literal key or a quoted key.
+ * @remarks In TOML, inline nodes are located before standard nodes. Since arrays are presented as inline node, they
+ * will be inserted before any standard node (table or table array if defined as standard node).
+ * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
+ * square brackets. Can be empty, causing the node to be inserted at the end.
+ * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
+ * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
+ * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
+ * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
+ * parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
- IInterfaceAccess InsertArray(in uint32 uiIndex, in u8string ssName);
-
- /**
- * @brief Insertion preference for tables and table arrays, being standard or inline.
- */
- enum EInsertPreference
- {
- prefer_standard = 0, ///< When the parent node is not inline, the node will be inserted as standard node.
- prefer_inline = 1, ///< The node will be inserted as inline node.
- };
+ IInterfaceAccess InsertArray(in u8string ssInsertBefore, in u8string ssName);
/**
* @brief Insert a table into the collection at the location before the supplied index.
- * @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
- * collection count to insert the node at the end of the collection. Table nodes cannot be inserted before value nodes
- * or arrays. If the index is referencing a position before a value node or an array, the index is automatically
- * corrected.
- * @param[in] ssName Name of the table node to insert. Will be ignored if the parent node is an array collection.
- * The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
- * allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
- * literal key or a quoted key.
+ * @remarks In TOML, inline nodes are located before standard nodes. Tables can be inserted as inline node, in which
+ * case they will be inserted before any standard node (table or table array if defined as standard node).
+ * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
+ * square brackets. Can be empty, causing the node to be inserted at the end.
+ * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
+ * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
+ * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
+ * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
+ * parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] ePreference The preferred form of the node to be inserted.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
- IInterfaceAccess InsertTable(in uint32 uiIndex, in u8string ssName, in EInsertPreference ePreference);
+ IInterfaceAccess InsertTable(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);
/**
* @brief Insert a table array into the collection at the location before the supplied index.
- * @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
- * collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
- * nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
- * corrected.
- * @param[in] ssName Name of the array node to insert. Will be ignored if the parent node is also an array collection.
- * The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
- * allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
- * literal key or a quoted key.
+ * @remarks In TOML, inline nodes are located before standard nodes. Table arrays can be inserted as inline node, in
+ * which case they will be inserted before any standard node (table or table array if defined as standard node).
+ * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
+ * square brackets. Can be empty, causing the node to be inserted at the end.
+ * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
+ * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
+ * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
+ * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
+ * parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] ePreference The preferred form of the node to be inserted.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
- IInterfaceAccess InsertTableArray(in uint32 uiIndex, in u8string ssName, in EInsertPreference ePreference);
+ IInterfaceAccess InsertTableArray(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);
/**
* @brief The result of the TOML string to insert.
@@ -358,17 +365,15 @@ module sdv
* @brief Insert a TOML string as a child of the current collection node. If the collection is a table, the TOML string
* should contain values and inline/external/array-table nodes with names. If the collection is an array, the TOML
* string should contain and inline table nodes without names.
- * @attention Even though the TOML might be defining the node(s) in standard form, if the parent node is an inline node,
- * the node will be inserted as inline node.
- * @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
- * collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
- * nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
- * corrected.
+ * @remarks In TOML, inline nodes are located before standard nodes. Dependable on the nodes defined in the TOML they
+ * might be transferred to inline or they might be inserted at a different location.
+ * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
+ * square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssTOML The TOML string to insert. This string can hold one or more nodes that should be inserted.
* @param[in] bRollbackOnFailure If only part of the nodes could be inserted, no node will be inserted.
* @return The result of the insertion.
*/
- EInsertResult InsertTOML(in uint32 uiIndex, in u8string ssTOML, in boolean bRollbackOnFailure);
+ EInsertResult InsertTOML(in u8string ssInsertBefore, in u8string ssTOML, in boolean bRollbackOnFailure);
};
/**
diff --git a/export/support/any.inl b/export/support/any.inl
index 0442a91..23f0cdc 100644
--- a/export/support/any.inl
+++ b/export/support/any.inl
@@ -24,6 +24,9 @@
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 26495)
+#else
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
namespace sdv
@@ -1738,6 +1741,8 @@ namespace sdv
#ifdef _MSC_VER
#pragma warning(pop)
+#else
+ #pragma GCC diagnostic pop
#endif
#endif // !defined SDV_ANY_INL
\ No newline at end of file
diff --git a/export/support/app_control.h b/export/support/app_control.h
index 77135ed..cdffaa0 100644
--- a/export/support/app_control.h
+++ b/export/support/app_control.h
@@ -65,6 +65,7 @@ namespace sdv
bool Startup(const std::string& rssConfig)
{
IAppControl* pAppControl = core::GetCore() ? core::GetCore() : nullptr;
+
if (!pAppControl) return false;
if (m_eState != EAppOperationState::not_started) return false;
try
@@ -78,45 +79,6 @@ namespace sdv
{
m_eContext = pAppContext->GetContextType();
m_uiInstanceID = pAppContext->GetInstanceID();
- m_uiRetries = pAppContext->GetRetries();
- }
-
- // Automatically connect to the server
- if (m_eContext == EAppContext::external)
- {
- // Try to connect
- m_ptrServerRepository = sdv::com::ConnectToLocalServerRepository(m_uiInstanceID, m_uiRetries);
- if (!m_ptrServerRepository)
- {
- if (!ConsoleIsSilent())
- std::cerr << "ERROR: Failed to connect to the server repository." << std::endl;
- Shutdown();
- return false;
- }
-
- // Get access to the module control service
- sdv::core::IObjectAccess* pObjectAccess = m_ptrServerRepository.GetInterface();
- const sdv::core::IRepositoryControl* pRepoControl = nullptr;
- if (pObjectAccess)
- pRepoControl = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("RepositoryService")).
- GetInterface();
- if (!pRepoControl)
- {
- if (!ConsoleIsSilent())
- std::cerr << "ERROR: Failed to access the server repository." << std::endl;
- return false;
- }
-
- // Link the local repository to the server repository.
- sdv::core::ILinkCoreRepository* pLinkCoreRepo =
- sdv::core::GetObject("RepositoryService");
- if (!pLinkCoreRepo)
- {
- if (!ConsoleIsSilent())
- std::cerr << "ERROR: Cannot link local and server repositories." << std::endl;
- return false;
- }
- pLinkCoreRepo->LinkCoreRepository(m_ptrServerRepository);
}
return bRet;
@@ -154,23 +116,6 @@ namespace sdv
*/
void Shutdown()
{
- // Disconnect local and remote repositories.
- if (m_ptrServerRepository)
- {
- // Link the local repository to the server repository.
- sdv::core::ILinkCoreRepository* pLinkCoreRepo =
- sdv::core::GetObject("RepositoryService");
- if (!pLinkCoreRepo)
- {
- if (!ConsoleIsSilent())
- std::cerr << "ERROR: Cannot unlink local and server repositories." << std::endl;
- } else
- pLinkCoreRepo->UnlinkCoreRepository();
- }
-
- // Disconnect from the server (if connected at all).
- m_ptrServerRepository.Clear();
-
// Shutdown.
IAppControl* pAppControl = core::GetCore() ? core::GetCore() : nullptr;
try
@@ -194,28 +139,86 @@ namespace sdv
return m_eState == EAppOperationState::running;
}
+ /**
+ * @brief Get the absolute path to the currently run executable
+ * @return Absolute std::filesystem::path to the currently run executable
+ */
+ static std::filesystem::path GetAppDirectory()
+ {
+ static std::filesystem::path pathExeDir;
+ if (!pathExeDir.empty())
+ return pathExeDir;
+#ifdef _WIN32
+ // Windows specific
+ std::wstring ssPath(32768, '\0');
+ GetModuleFileNameW(NULL, ssPath.data(), static_cast(ssPath.size() - 1));
+#elif defined __linux__
+ // Linux specific
+ std::string ssPath(PATH_MAX + 1, '\0');
+ const ssize_t nCount = readlink("/proc/self/exe", ssPath.data(), PATH_MAX);
+ if (nCount < 0 || nCount >= PATH_MAX)
+ return pathExeDir; // some error
+ ssPath.at(nCount) = '\0';
+#else
+ #error OS is not supported!
+#endif
+ pathExeDir = std::filesystem::path{ssPath.c_str()}.parent_path() / ""; // To finish the folder path with (back)slash
+ return pathExeDir;
+ }
+
+ /**
+ * @brief Get the filename of the currently run executable
+ * @return The filename to the currently run executable
+ */
+ static std::filesystem::path GetAppFilename()
+ {
+ static std::filesystem::path pathExeFilename;
+ if (!pathExeFilename.empty())
+ return pathExeFilename;
+#ifdef _WIN32
+ // Windows specific
+ std::wstring ssPath(32768, '\0');
+ GetModuleFileNameW(NULL, ssPath.data(), static_cast(ssPath.size() - 1));
+#elif defined __linux__
+ // Linux specific
+ std::string ssPath(PATH_MAX + 1, '\0');
+ const ssize_t nCount = readlink("/proc/self/exe", ssPath.data(), PATH_MAX);
+ if (nCount < 0 || nCount >= PATH_MAX)
+ return pathExeFilename; // some error
+ ssPath.at(nCount) = '\0';
+#else
+ #error OS is not supported!
+#endif
+ pathExeFilename = std::filesystem::path{ssPath.c_str()}.filename();
+ return pathExeFilename;
+ }
+
+
/**
* @brief Get the SDV_FRAMEWORK_RUNTIME environment variable for this application.
- * @return Path directing to the SDV V-API Framework directory if available or an empty path if not.
+ * @remarks If the environment variable is empty or if the variable contains a relative path, the path will be enhanced
+ * with the application path.
+ * @return Absolute path directing to the SDV Vehicle API Framework directory.
*/
static std::filesystem::path GetFrameworkRuntimeDirectory()
{
+ std::filesystem::path path;
#ifdef _WIN32
const wchar_t* szFrameworkDir = _wgetenv(L"SDV_FRAMEWORK_RUNTIME");
- if (!szFrameworkDir) return {};
- return szFrameworkDir;
+ if (szFrameworkDir) path = szFrameworkDir;
#elif defined __unix__
const char* szFrameworkDir = getenv("SDV_FRAMEWORK_RUNTIME");
- if (!szFrameworkDir) return {};
- return szFrameworkDir;
+ if (szFrameworkDir) path = szFrameworkDir;
#else
#error The OS is not supported!
#endif
+ if (path.empty() || path.is_relative()) path = GetAppDirectory() / path;
+ return path.lexically_normal();
}
/**
* @brief Set or overwrite the SDV_FRAMEWORK_RUNTIME environment variable for this application.
- * @param[in] rpathDir Reference of the path directing to the SDV V-API Framework directory.
+ * @param[in] rpathDir Reference of the path directing to the SDV Vehicle API Framework directory.
*/
static void SetFrameworkRuntimeDirectory(const std::filesystem::path& rpathDir)
{
@@ -232,26 +235,30 @@ namespace sdv
/**
* @brief Get the SDV_COMPONENT_INSTALL environment variable for this application.
- * @return Path directing to the SDV V-API component installation directory if available or an empty path if not.
+ * @remarks If the environment variable is empty, the runtime directory is taken. If the variable contains a relative
+ * path, the path will be enhanced with the application path.
+ * @return Absolute path directing to the SDV Vehicle API component installation directory.
*/
static std::filesystem::path GetComponentInstallDirectory()
{
+ std::filesystem::path path;
#ifdef _WIN32
const wchar_t* szComponentDir = _wgetenv(L"SDV_COMPONENT_INSTALL");
- if (!szComponentDir) return {};
- return szComponentDir;
+ if (szComponentDir) path = szComponentDir;
#elif defined __unix__
const char* szComponentDir = getenv("SDV_COMPONENT_INSTALL");
- if (!szComponentDir) return {};
- return szComponentDir;
+ if (szComponentDir) path = szComponentDir;
#else
#error The OS is not supported!
#endif
+ if (path.empty()) return GetFrameworkRuntimeDirectory();
+ if (path.is_relative()) path = GetAppDirectory() / path;
+ return path.lexically_normal();
}
/**
* @brief Set or overwrite the SDV_COMPONENT_INSTALL environment variable for this application.
- * @param[in] rpathDir Reference of the path directing to the SDV V-API component installation directory.
+ * @param[in] rpathDir Reference of the path directing to the SDV Vehicle API component installation directory.
*/
static void SetComponentInstallDirectory(const std::filesystem::path& rpathDir)
{
@@ -527,8 +534,7 @@ namespace sdv
EAppOperationState m_eState = EAppOperationState::not_started; ///< Application state.
EAppContext m_eContext = EAppContext::no_context; ///< Application context.
uint32_t m_uiInstanceID = 0u; ///< Core instance.
- uint32_t m_uiRetries = 0u; ///< Number of retries to establish a connection.
- sdv::TObjectPtr m_ptrServerRepository; ///< Server repository interface.
+ uint32_t m_uiConnectRetries = 0u; ///< Number of retries to establish a connection.
};
} // namespace app
} // namespace sdv
diff --git a/export/support/component_impl.h b/export/support/component_impl.h
index 3a39a92..065b8ad 100644
--- a/export/support/component_impl.h
+++ b/export/support/component_impl.h
@@ -20,6 +20,8 @@
#include
#include
#include
+#include
+#include
#include "../interfaces/core_types.h"
#include "../interfaces/core.h"
@@ -683,9 +685,9 @@ namespace sdv
/**
* @brief Initialize the object. Overload of IObjectControl::Initialize.
- * @param[in] ssObjectConfig Optional configuration string.
+ * @param[in] sObjectInfo The registration information of this object.
*/
- virtual void Initialize(/*in*/ const u8string& ssObjectConfig) override
+ virtual void Initialize(/*in*/ const SObjectInfo& sObjectInfo) override
{
// Not started before or ended completely?
if (GetObjectState() != EObjectState::initialization_pending && GetObjectState() != EObjectState::destruction_pending)
@@ -700,19 +702,19 @@ namespace sdv
// Initialize the parameter map.
InitParamMap();
- // Copy the configuration
- m_ssObjectConfig = ssObjectConfig;
+ // Copy the object information
+ m_sSelf = sObjectInfo;
// Prepare initialization
OnPreInitialize();
// Parse the object configuration if there is any.
- if (!ssObjectConfig.empty())
+ if (!m_sSelf.ssConfig.empty())
{
try
{
// Parse the config TOML.
- toml::CTOMLParser parser(ssObjectConfig);
+ toml::CTOMLParser parser(m_sSelf.ssConfig);
if (!parser.IsValid())
{
m_eObjectState = EObjectState::config_error;
@@ -781,6 +783,15 @@ namespace sdv
return m_eObjectState;
}
+ /**
+ * @brief Get information about ourself.
+ * @return The object information about ourself.
+ */
+ const SObjectInfo& Self() const
+ {
+ return m_sSelf;
+ }
+
/**
* @brief Set the component operation mode. Overload of IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
@@ -831,15 +842,11 @@ namespace sdv
}
/**
- * @brief Get the object configuration for persistence.
+ * @brief Build the object configuration from the parameter map and the stored initial configuration.
* @return The object configuration as TOML string.
*/
- virtual u8string GetObjectConfig() const override
+ virtual u8string BuildObjectConfig() const
{
- // During the initialization, return the stored object configuration.
- if (m_eObjectState == EObjectState::initializing || m_eObjectState == EObjectState::initialization_pending)
- return m_ssObjectConfig;
-
// Split path function (splits the group from the parameter names)
auto fnSplitPath = [](const u8string& rssPath) -> std::pair
{
@@ -849,13 +856,10 @@ namespace sdv
return std::make_pair(rssPath.substr(0, nPos), rssPath.substr(nPos + 1));
};
- // Create a new configuration string from the parameters.
- auto seqParameters = GetParamPaths();
- if (seqParameters.empty()) return {};
-
// Iterate through the list of parameter names and create the TOML entries for it.
+ auto seqParameters = GetParamPaths();
u8string ssGroup;
- toml::CTOMLParser parser("");
+ toml::CTOMLParser parser(m_sSelf.ssConfig);
toml::CNodeCollection table(parser);
for (auto ssParamPath : seqParameters)
{
@@ -863,7 +867,7 @@ namespace sdv
auto ptrParam = FindParamObject(ssParamPath);
// Read only and temporary parameters are not stored
- if ((!ptrParam->Locked() && ptrParam->ReadOnly()) || !ptrParam->Temporary())
+ if ((!ptrParam->Locked() && ptrParam->ReadOnly()) || ptrParam->Temporary())
continue;
// Get the value
@@ -877,7 +881,9 @@ namespace sdv
// Need to add a group?
if (prParam.first != ssGroup)
{
- table = parser.AddTable(prParam.first);
+ table = parser.GetDirect(prParam.first);
+ if (!table)
+ table = parser.AddTable(prParam.first);
ssGroup = prParam.first;
}
@@ -888,6 +894,20 @@ namespace sdv
return parser.GetTOML();
}
+ /**
+ * @brief Get the object configuration for persistence. Overload of IObjectControl::GetObjectConfig.
+ * @return The object configuration as TOML string.
+ */
+ virtual u8string GetObjectConfig() const override
+ {
+ // During the initialization, return the stored object configuration.
+ if (m_eObjectState == EObjectState::initializing || m_eObjectState == EObjectState::initialization_pending)
+ return m_sSelf.ssConfig;
+
+
+ return BuildObjectConfig();
+ }
+
/**
* @brief Shutdown called before the object is destroyed. Overload of IObjectControl::Shutdown.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the
@@ -930,7 +950,7 @@ namespace sdv
* @post Reset by switching to configuration mode.
*/
void SetObjectIntoRuntimeErrorState()
- {
+ {
if (m_eObjectState == EObjectState::running)
m_eObjectState = EObjectState::runtime_error;
}
@@ -992,6 +1012,12 @@ namespace sdv
*/
virtual void OnShutdown() {}
+ /**
+ * @brief Last function called before destruction. The object integrity is still in tact. It can be assumed that all
+ * dependencies to the object have been released.
+ */
+ virtual void OnDestroy() {}
+
/**
* @brief Interface map
*/
@@ -1002,7 +1028,8 @@ namespace sdv
private:
std::atomic m_eObjectState = EObjectState::initialization_pending; ///< Object state
- std::string m_ssObjectConfig; ///< Copy of the configuration TOML.
+ CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Manage module lifetime.
+ SObjectInfo m_sSelf; ///< Information about ourself.
};
/**
@@ -1022,6 +1049,206 @@ namespace sdv
END_SDV_INTERFACE_MAP()
};
+ /**
+ * @brief Lifetime control implementation class.
+ */
+ class CLifetimeControlImpl : public virtual IInterfaceAccess, public IObjectLifetime, protected IObjectDestroy
+ {
+ public:
+ /**
+ * @brief Default constructor
+ */
+ CLifetimeControlImpl()
+ {}
+
+ /**
+ * @brief Deleted copy constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ */
+ CLifetimeControlImpl(const CLifetimeControlImpl& rClass) = delete;
+
+ /**
+ * @brief Deleted move constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ */
+ CLifetimeControlImpl(CLifetimeControlImpl&& rClass) = delete;
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~CLifetimeControlImpl()
+ {}
+
+ // Interface map (IObjectDestroy is not exposed)
+ BEGIN_SDV_INTERFACE_MAP()
+ SDV_INTERFACE_ENTRY(IObjectLifetime)
+ END_SDV_INTERFACE_MAP()
+
+ /**
+ * @brief Deleted copy assignment constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ * @return Reference to this class.
+ */
+ CLifetimeControlImpl& operator=(const CLifetimeControlImpl& rClass) = delete;
+
+ /**
+ * @brief Deleted move assignment constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ * @return Reference to this class.
+ */
+ CLifetimeControlImpl& operator=(CLifetimeControlImpl&& rClass) = delete;
+
+ /**
+ * @brief Increment the lifetime. Needs to be balanced by a call to Decrement. Overload of IObjectLifetime::Increment.
+ */
+ virtual void Increment() override
+ {
+ m_uiLifetimeCnt++;
+ }
+
+ /**
+ * @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
+ * IObjectDestroy interface). Overload of IObjectLifetime::Decrement.
+ * @return Returns 'true' if the object was destroyed, false if not.
+ */
+ virtual bool Decrement() override
+ {
+ if (m_uiLifetimeCnt && !(--m_uiLifetimeCnt))
+ {
+ DestroyObject();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @brief Get the current lifetime count. Overload of IObjectLifetime::GetCount.
+ * @remarks The GetCount function returns a momentary value, which can be changed at any moment.
+ * @return Returns the current counter value.
+ */
+ virtual uint32_t GetCount() const override
+ {
+ return m_uiLifetimeCnt;
+ }
+
+ protected:
+ /**
+ * @brief Destroy the object. Default implementation deletes 'this'. Overload of IObjectDestroy::DestroyObject.
+ * @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
+ */
+ virtual void DestroyObject() override
+ {
+ delete this;
+ }
+
+ private:
+ CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Module lifetime
+ std::atomic_uint32_t m_uiLifetimeCnt = 1; ///< Lifetime reference counter
+ };
+
+ /**
+ * @brief Lifetime control implementation class based on shared pointer.
+ * @tparam TClass The type of class deriving CSharedLifetimeControlImpl class.
+ */
+ template
+ class CSharedLifetimeControlImpl : public std::enable_shared_from_this, public CLifetimeControlImpl
+ {
+ public:
+ /**
+ * @brief Default constructor
+ */
+ CSharedLifetimeControlImpl()
+ {}
+
+ /**
+ * @brief Deleted copy constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ */
+ CSharedLifetimeControlImpl(const CSharedLifetimeControlImpl& rClass) = delete;
+
+ /**
+ * @brief Deleted move constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ */
+ CSharedLifetimeControlImpl(CSharedLifetimeControlImpl&& rClass) = delete;
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~CSharedLifetimeControlImpl()
+ {
+ }
+
+ // Interface map (IObjectDestroy is not exposed)
+ BEGIN_SDV_INTERFACE_MAP()
+ SDV_INTERFACE_ENTRY(IObjectLifetime)
+ END_SDV_INTERFACE_MAP()
+
+ /**
+ * @brief Deleted copy assignment constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ * @return Reference to this class.
+ */
+ CSharedLifetimeControlImpl& operator=(const CSharedLifetimeControlImpl& rClass) = delete;
+
+ /**
+ * @brief Deleted move assignment constructor.
+ * @param[in] rClass Reference to the class to copy from.
+ * @return Reference to this class.
+ */
+ CSharedLifetimeControlImpl& operator=(CSharedLifetimeControlImpl&& rClass) = delete;
+
+ /**
+ * @brief Increment the lifetime. Needs to be balanced by a call to Decrement. Overload of IObjectLifetime::Increment.
+ */
+ virtual void Increment() override
+ {
+ if (!m_uiLifetimeCnt++)
+ m_ptrLocking = std::enable_shared_from_this::shared_from_this();
+ }
+
+ /**
+ * @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
+ * IObjectDestroy interface). Overload of IObjectLifetime::Decrement.
+ * @return Returns 'true' if the object was destroyed, false if not.
+ */
+ virtual bool Decrement() override
+ {
+ if (m_uiLifetimeCnt && !(--m_uiLifetimeCnt))
+ {
+ DestroyObject();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @brief Get the current lifetime count. Overload of IObjectLifetime::GetCount.
+ * @remarks The GetCount function returns a momentary value, which can be changed at any moment.
+ * @return Returns the current counter value.
+ */
+ virtual uint32_t GetCount() const override
+ {
+ return m_uiLifetimeCnt;
+ }
+
+ protected:
+ /**
+ * @brief Destroy the object. Default implementation deletes 'this'. Overload of IObjectDestroy::DestroyObject.
+ * @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
+ */
+ virtual void DestroyObject() override
+ {
+ // Reset the locking; this might delete the class if no other references are present.
+ m_ptrLocking.reset();
+ }
+
+ private:
+ std::shared_ptr m_ptrLocking; ///< Holder of the instance of the class during lifetime.
+ CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Module lifetime
+ std::atomic_uint32_t m_uiLifetimeCnt = 0; ///< Lifetime reference counter
+ };
+
/////////////////////////////////////////
// Object control class implementation //
/////////////////////////////////////////
@@ -1114,6 +1341,7 @@ namespace sdv
auto objectPtr = std::move(*iter);
m_vecActiveObjects.erase(iter);
lockObjects.unlock();
+ objectPtr->OnDestroy();
objectPtr = nullptr;
if (m_uiActiveObjectCount) --m_uiActiveObjectCount;
return;
diff --git a/export/support/interface_ptr.h b/export/support/interface_ptr.h
index e10b40b..9249a2f 100644
--- a/export/support/interface_ptr.h
+++ b/export/support/interface_ptr.h
@@ -389,7 +389,13 @@ namespace sdv
template
TIfc* GetInterface() const
{
- return m_pInterface ? m_pInterface.load()->GetInterface(GetInterfaceId()).template get() : nullptr;
+ try
+ {
+ return m_pInterface ? m_pInterface.load()->GetInterface(GetInterfaceId()).template get() : nullptr;
+ } catch (const XSysExcept&)
+ {
+ return nullptr;
+ }
}
private:
diff --git a/export/support/local_service_access.h b/export/support/local_service_access.h
index 3375315..971a4e6 100644
--- a/export/support/local_service_access.h
+++ b/export/support/local_service_access.h
@@ -18,10 +18,17 @@
#include "../interfaces/log.h"
#include "../interfaces/repository.h"
#include "../interfaces/com.h"
+#include "../interfaces/app.h"
+#include "../interfaces/param.h"
+#include "../interfaces/permission.h"
#include "interface_ptr.h"
+#include
+#include
+#include
#include
#include
-
+#include
+#include
#ifdef __GNUC__
// Needed for getpid()
#include
@@ -49,9 +56,11 @@ namespace sdv
*/
inline TInterfaceAccessPtr GetObject(const std::string& rssObjectName)
{
- if (!GetCore()) return nullptr;
+ if (!GetCore())
+ return nullptr;
IObjectAccess* pRepository = GetCore();
- if (!pRepository) return nullptr;
+ if (!pRepository)
+ return nullptr;
return pRepository->GetObject(rssObjectName);
}
@@ -63,9 +72,11 @@ namespace sdv
*/
inline TInterfaceAccessPtr GetObject(TObjectID tObjectID)
{
- if (!GetCore()) return nullptr;
+ if (!GetCore())
+ return nullptr;
IObjectAccess* pRepository = GetCore();
- if (!pRepository) return nullptr;
+ if (!pRepository)
+ return nullptr;
return pRepository->GetObjectByID(tObjectID);
}
#else
@@ -113,21 +124,23 @@ namespace sdv
}
/**
- * @brief Log function enables logging for SDV.
- * @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
- * @param[in] rssSrcFile Name of the file from which the message is logged.
- * @param[in] uiSrcLine Line of the file from which the message is logged.
- * @param[in] rssMessage Reference to the log message to be logged.
- */
+ * @brief Log function enables logging for SDV.
+ * @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
+ * @param[in] rssSrcFile Name of the file from which the message is logged.
+ * @param[in] uiSrcLine Line of the file from which the message is logged.
+ * @param[in] rssMessage Reference to the log message to be logged.
+ */
inline void Log(ELogSeverity eSeverity, const u8string& rssSrcFile, uint32_t uiSrcLine, const u8string& rssMessage)
{
ILogger* pLogger = GetCore() ? GetCore() : nullptr;
#ifdef _WIN32
- if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
+ if (pLogger)
+ pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
#elif defined __unix__
- if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
+ if (pLogger)
+ pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
#else
-#error The OS is currently not supported!
+ #error The OS is currently not supported!
#endif
}
@@ -137,34 +150,34 @@ namespace sdv
*/
#define SDV_LOG(severity, ...) sdv::core::internal::CSDVLogImpl(severity, __FILE__, __LINE__, __VA_ARGS__)
- /**
+ /**
* @brief Log a trace message with line and position.
*/
#define SDV_LOG_TRACE(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::trace, __FILE__, __LINE__, __VA_ARGS__)
- /**
- * @brief Log a debug message with line and position.
- */
+ /**
+ * @brief Log a debug message with line and position.
+ */
#define SDV_LOG_DEBUG(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::debug, __FILE__, __LINE__, __VA_ARGS__)
- /**
- * @brief Log an information message with line and position.
- */
+ /**
+ * @brief Log an information message with line and position.
+ */
#define SDV_LOG_INFO(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::info, __FILE__, __LINE__, __VA_ARGS__)
- /**
- * @brief Log a warning message with line and position.
- */
+ /**
+ * @brief Log a warning message with line and position.
+ */
#define SDV_LOG_WARNING(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::warning, __FILE__, __LINE__, __VA_ARGS__)
- /**
- * @brief Log an error message with line and position.
- */
+ /**
+ * @brief Log an error message with line and position.
+ */
#define SDV_LOG_ERROR(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::error, __FILE__, __LINE__, __VA_ARGS__)
- /**
- * @brief Log a fatal message with line and position.
- */
+ /**
+ * @brief Log a fatal message with line and position.
+ */
#define SDV_LOG_FATAL(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::fatal, __FILE__, __LINE__, __VA_ARGS__)
namespace internal
@@ -176,22 +189,22 @@ namespace sdv
* @param[in] uiSrcLine Line of the file from which the message is logged. Specified by C++ standard.
* @param[in] ...args identifier specified by C++ standard that uses the ellipsis notation in the parameters.
*/
- template
- inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&& ...args)
+ template
+ inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&&... args)
{
std::ostringstream stream;
(stream << ... << std::forward(args));
Log(eSeverity, szSrcFile ? szSrcFile : "", uiSrcLine, stream.str().c_str());
}
- }
+ } // namespace internal
/**
* @brief Create a utility
* @param[in] rssUtilityName Reference to the utility name.
* @param[in] rssUtilityConfig Optional reference to the utility configuration.
* @return Smart pointer to the utility or NULL when the utility could not be found.
- */
+ */
inline TObjectPtr CreateUtility(const std::string& rssUtilityName, const std::string& rssUtilityConfig = std::string())
{
TInterfaceAccessPtr ptrRepository = GetObject("RepositoryService");
@@ -199,8 +212,529 @@ namespace sdv
if (!pUtilityCreate) return nullptr;
return pUtilityCreate->CreateUtility(rssUtilityName, rssUtilityConfig);
}
- } // namespace core
+ /**
+ * @brief Get a parameter from the object smart pointer.
+ * @param[in] pParameters Pointer to the parameter map interface of an object.
+ * @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
+ * @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
+ * found.
+ * @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
+ * bNoExcept was set.
+ */
+ inline any_t GetParameter(const IParameters* pParameters, const std::string& rssParamName, bool bNoExcept = true)
+ {
+ if (!pParameters)
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("The object doesn't expose IParameters interface.");
+ }
+ any_t any = pParameters->GetParam(rssParamName);
+ if (any.empty())
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("The parameter could not be found.");
+ }
+ return any;
+ }
+
+ /**
+ * @brief Get a parameter from the parameter interface.
+ * @param[in] rptrObject Reference to object smart pointer to the the parameter of.
+ * @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
+ * @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
+ * found.
+ * @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
+ * bNoExcept was set.
+ */
+ inline any_t GetParameter(const TInterfaceAccessPtr& rptrObject, const std::string& rssParamName, bool bNoExcept = true)
+ {
+ const IParameters* pParameters = rptrObject.GetInterface();
+ if (!pParameters)
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("The object doesn't expose IParameters interface.");
+ }
+ return GetParameter(pParameters, rssParamName, bNoExcept);
+ }
+
+ /**
+ * @brief Get a parameter from the object with the supplied name.
+ * @param[in] rssObjectName Reference to the string containing the name of the object or service.
+ * @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
+ * @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
+ * found.
+ * @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
+ * bNoExcept was set.
+ */
+ inline any_t GetParameter(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
+ {
+ TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
+ if (!ptrObject)
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
+ }
+ return GetParameter(ptrObject, rssParamName, bNoExcept);
+ }
+
+ /**
+ * @brief Get a parameter from the object with the supplied name. Resolve enums and bitmask objects in the returned
+ * parameter string.
+ * @param[in] rssObjectName Reference to the string containing the name of the object or service.
+ * @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
+ * @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
+ * found.
+ * @return Returns the value of the parameter as a text string or an empty string when the object or the parameter could
+ * not be found and bNoExcept was set.
+ */
+ inline std::string GetParameterExpand(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
+ {
+ TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
+ if (!ptrObject)
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
+ }
+
+ const IParameters* pParameters = ptrObject.GetInterface();
+ if (!pParameters)
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("The object doesn't expose IParameters interface.");
+ }
+ any_t any = pParameters->GetParam(rssParamName);
+ if (any.empty())
+ {
+ if (bNoExcept) return {};
+ throw std::runtime_error("The parameter could not be found.");
+ }
+
+ SParamInfo sParamInfo = pParameters->GetParamInfo(rssParamName);
+ if (sParamInfo.get_switch() == EParamType::enum_param)
+ {
+ for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sEnumInfo.seqLabels)
+ {
+ if (rsLabel.anyValue == any)
+ return rsLabel.ssLabel;
+ }
+ }
+ if (sParamInfo.get_switch() == EParamType::bitmask_param)
+ {
+ uint64_t uiValue = static_cast(any);
+ std::stringstream sstreamValue;
+ for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sBitmaskInfo.seqLabels)
+ {
+ uint64_t uiValueLabel = static_cast(rsLabel.anyValue);
+ if (uiValue & uiValueLabel)
+ {
+ if (sstreamValue.rdbuf()->in_avail()) // Has characters
+ sstreamValue << "|";
+ sstreamValue << rsLabel.ssLabel;
+ uiValue = uiValue & ~uiValueLabel;
+ }
+ }
+ if (uiValue) // Not all bits have labels
+ {
+ if (sstreamValue.rdbuf()->in_avail()) // Has characters
+ sstreamValue << "|";
+ sstreamValue << uiValue;
+ }
+ return sstreamValue.str();
+ }
+ return any;
+ }
+
+ /// Internal namespace
+ namespace internal
+ {
+ /**
+ * @brief Trim whitespace at the begin and end of the text.
+ * @param[in] rssText Reference to the text to trim whitespace for.
+ * @return The trimmed text.
+ */
+ inline std::string TrimWhitespace(const std::string& rssText)
+ {
+ size_t nFirst = rssText.find_first_not_of(" \t\r\n");
+ if (nFirst == std::string::npos) return "";
+ size_t nLast = rssText.find_last_not_of(" \t\r\n");
+ return rssText.substr(nFirst, (nLast - nFirst + 1));
+ }
+
+ /**
+ * @brief Helper function to safely check if a string contains a valid, unescaped $(...) sequence.
+ * @param[in] rssText The text to check.
+ * @return Returns whether the text represents a valid variable.
+ */
+ inline bool ContainsValidVariable(const std::string& rssText)
+ {
+ size_t nLength = rssText.length();
+ size_t nIndex = 0;
+
+ while (nIndex < nLength)
+ {
+ if (rssText[nIndex] == '\\')
+ {
+ // Skip the escape and the escaped character
+ nIndex += 2;
+ }
+ else if (rssText[nIndex] == '$')
+ {
+ // Check if it forms the start of a token sequence '$( '
+ if (nIndex + 1 < nLength && rssText[nIndex + 1] == '(')
+ {
+ size_t nClose = rssText.find(')', nIndex + 2);
+ if (nClose != std::string::npos)
+ {
+ // Found a valid structural candidate
+ return true;
+ }
+ }
+ nIndex++;
+ }
+ else
+ {
+ nIndex++;
+ }
+ }
+ return false;
+ }
+ } // namespace internal
+
+ /**
+ * @brief Resolves embedded object parameter variables formatted as $(object:param) within a text string.
+ * @param[in] rssText The source text containing potential variables and backslash escapes.
+ * @param[in] bRecursive If true, continues resolving until no more unescaped variables remain.
+ * @param[in] bNoExcept If true, returns an empty string for errors; if false, throws std::runtime_error.
+ * @return The fully resolved text string.
+ */
+ inline std::string ResolveText(const std::string& rssText, bool bRecursive = true, bool bNoExcept = true)
+ {
+ std::string ssCurrentText = rssText;
+ bool bMayHaveMoreVariables = true;
+
+ while (bMayHaveMoreVariables)
+ {
+ bMayHaveMoreVariables = false;
+ std::string ssResult = "";
+ ssResult.reserve(ssCurrentText.length()); // Pre-allocate memory for performance
+
+ size_t nLength = ssCurrentText.length();
+ size_t nIndex = 0;
+
+ while (nIndex < nLength)
+ {
+ char cCurrent = ssCurrentText[nIndex];
+
+ // Handle backslash escape sequences
+ if (cCurrent == '\\')
+ {
+ // Check if the next character is a '$'
+ if (nIndex + 1 < nLength && ssCurrentText[nIndex + 1] == '$')
+ {
+ ssResult.push_back('$'); // Strip the escape character, keep the literal '$'
+ nIndex += 2;
+ }
+ else
+ {
+ ssResult.push_back('\\'); // Preserve other backslashes for paths
+ nIndex++;
+ }
+ }
+ // Identify potential variables
+ else if (cCurrent == '$')
+ {
+ // extension 2: Only throw an error or treat as a variable if it is
+ // explicitly part of a dynamic sequence tracking towards a '$(...)' match.
+ if (nIndex + 1 >= nLength || ssCurrentText[nIndex + 1] != '(')
+ {
+ // It is a loose literal '$' (like currency). Keep it and do not throw.
+ ssResult.push_back('$');
+ nIndex++;
+ continue;
+ }
+
+ size_t nVarStart = nIndex + 2; // Position right after "$("
+ size_t nVarEnd = ssCurrentText.find(')', nVarStart);
+
+ // Validate that a matching closing parenthesis exists
+ if (nVarEnd == std::string::npos)
+ {
+ if (!bNoExcept)
+ throw std::runtime_error(
+ "Format error: Missing closing parenthesis ')' for variable starting at index "
+ + std::to_string(nIndex));
+ return "";
+ }
+
+ // Extract the inner payload block
+ std::string sVariableContent = ssCurrentText.substr(nVarStart, nVarEnd - nVarStart);
+ size_t nColonPos = sVariableContent.find(':');
+
+ // Validate that the delimiter ':' separates object and parameter names
+ if (nColonPos == std::string::npos)
+ {
+ if (!bNoExcept)
+ throw std::runtime_error("Format error: Variable content '" + sVariableContent
+ + "' lacks an 'object:param' colon separator");
+ return "";
+ }
+
+ // Extract and clean whitespace before/after tokens, preserving inner spaces
+ std::string sObjName = internal::TrimWhitespace(sVariableContent.substr(0, nColonPos));
+ std::string sParamName = internal::TrimWhitespace(sVariableContent.substr(nColonPos + 1));
+
+ // Request the parameter.
+ std::string ssValue = GetParameterExpand(sObjName, sParamName, bNoExcept);
+
+ // Add the parameter to the string
+ ssResult.append(ssValue);
+
+ nIndex = nVarEnd + 1; // Move parsing index past the ')'
+ }
+ else
+ {
+ ssResult.push_back(cCurrent);
+ nIndex++;
+ }
+ }
+
+ ssCurrentText = ssResult;
+
+ // Exit immediately if recursive resolution was disabled
+ if (!bRecursive) break;
+
+ // extension 2: Intelligently analyze if a recursive processing loop is required
+ if (internal::ContainsValidVariable(ssCurrentText))
+ bMayHaveMoreVariables = true;
+ }
+
+ return ssCurrentText;
+ }
+
+ /**
+ * @brief Get the current access permission.
+ * @return The current access permission.
+ */
+ inline EAccessPermission GetCurrentAccessPermission()
+ {
+ IPermissionControl* pPermissionControl = GetCore();
+ if (!pPermissionControl)
+ return EAccessPermission::not_set;
+ return pPermissionControl->GetCurrentPermission();
+ }
+
+ /**
+ * @brief Get the current transmission from this thread and prepare a transfer to another thread.
+ * @return Transfer ID identifying the permission of this thread.
+ */
+ inline TPermissionTransferID TransferCurrentPermission()
+ {
+ IPermissionControl* pPermissionControl = GetCore();
+ if (!pPermissionControl) return 0u;
+ return pPermissionControl->TransferCurrentPermission();
+ }
+
+ /**
+ * @brief Class managing the lifetime of an access permission.
+ */
+ class CAccessPermission
+ {
+ // Friend functions
+ friend CAccessPermission RestrictAccessPermission(EAccessPermission);
+ friend CAccessPermission SetAccessPermission(TPermissionTransferID);
+
+ public:
+ /**
+ * @brief Default constructor
+ */
+ CAccessPermission() = default;
+
+ private:
+ /**
+ * @brief Constructor
+ * @param[in] tPermissionID The access permission to manage.
+ */
+ CAccessPermission(TPermissionID tPermissionID) : m_tPermissionID(tPermissionID)
+ {}
+
+ public:
+ /**
+ * @brief Copy constructor is deleted.
+ * @param[in] rPermission Reference to the permission to copy from.
+ */
+ CAccessPermission(const CAccessPermission& rPermission) = delete;
+
+ /**
+ * @brief Move constructor.
+ * @param[in] rPermission Reference to the permission to move from.
+ */
+ CAccessPermission(CAccessPermission&& rPermission) : m_tPermissionID(rPermission.m_tPermissionID)
+ {
+ rPermission.m_tPermissionID = 0u;
+ }
+
+ /**
+ * @brief Destructor
+ */
+ ~CAccessPermission()
+ {
+ Release();
+ }
+
+ /**
+ * @brief Copy assignment operator is deleted.
+ * @param[in] rPermission Reference to the permission to copy from.
+ * @return Reference to this class.
+ */
+ CAccessPermission& operator=(const CAccessPermission& rPermission) = delete;
+
+ /**
+ * @brief Move assignment operator.
+ * @param[in] rPermission Reference to the permission to move from.
+ * @return Reference to this class.
+ */
+ CAccessPermission& operator=(CAccessPermission&& rPermission)
+ {
+ m_tPermissionID = rPermission.m_tPermissionID;
+ rPermission.m_tPermissionID = 0u;
+ return *this;
+ }
+
+ /**
+ * @brief Boolean operator.
+ * @return Returns whether a valid permission ID is assigned to this class.
+ */
+ operator bool() const
+ {
+ return m_tPermissionID ? true : false;
+ }
+
+ /**
+ * @brief Does the access permission class contain a valid permission ID.
+ * @return Returns whether a valid permission ID is assigned to this class.
+ */
+ bool IsValid() const
+ {
+ return m_tPermissionID ? true : false;
+ }
+
+ /**
+ * @brief Release the permission.
+ */
+ void Release()
+ {
+ if (!m_tPermissionID) return;
+ IPermissionControl* pPermissionControl = GetCore();
+ if (!pPermissionControl) return;
+ pPermissionControl->ReleaseAccessPermission(m_tPermissionID);
+ m_tPermissionID = 0u;
+ }
+
+ private:
+ TPermissionID m_tPermissionID = 0u; ///< Permission ID to be managed by this class.
+ };
+
+ /**
+ * @brief Restrict the current access permission.
+ * @param[in] ePermission The permission the access should be restricted to.
+ * @return The access permission connected to this restriction. The lifetime of the access permission is managed by the
+ * returned class.
+ */
+ inline CAccessPermission RestrictAccessPermission(EAccessPermission ePermission)
+ {
+ IPermissionControl* pPermissionControl = GetCore();
+ if (!pPermissionControl) return {};
+ return pPermissionControl->RestrictAccessPermission(ePermission);
+ }
+
+ /**
+ * @brief Set the access permission from a transfer ID that defined the access permission of a different thread.
+ * @param[in] tTransferID The ID of the transferred access permission.
+ * @return The access permission for the current thread. The lifetime of the access permission is managed by the returned
+ * class.
+ */
+ inline CAccessPermission SetAccessPermission(TPermissionTransferID tTransferID)
+ {
+ IPermissionControl* pPermissionControl = GetCore();
+ if (!pPermissionControl) return {};
+ return pPermissionControl->SetAccessPermission(tTransferID);
+ }
+
+ /**
+ * @brief Secure thread implementation based on std::thread transferring the permissions from the creation thread to the
+ * execution thread.
+ */
+ class secure_thread : public std::thread
+ {
+ public:
+ /**
+ * @brief Default constructor
+ */
+ secure_thread() = default;
+
+ /**
+ * @brief Copy constructor is deleted.
+ * @param[in] rthread Reference to the thread object.
+ */
+ secure_thread(const secure_thread& rthread) = delete;
+
+ /**
+ * @brief Move constructor.
+ * @param[in] rthread Reference to the thread object.
+ */
+ secure_thread(secure_thread&& rthread) : std::thread(static_cast(rthread))
+ {}
+
+ /**
+ * @brief Assignment constructor for thread execution.
+ * @tparam F The function to execute.
+ * @tparam Args The argument types of the function to execute.
+ * @param[in] f Reference to the function.
+ * @param[in] args Reference to zero or more arguments.
+ */
+ template
+ explicit secure_thread(F&& f, Args&&... args)
+ {
+ static_cast(*this) = std::thread(
+ [](TPermissionTransferID tTransferID, auto&& function, auto&&... arguments)
+ {
+ CAccessPermission permission = SetAccessPermission(tTransferID);
+ std::invoke(std::forward(function), std::forward(arguments)...);
+ }, TransferCurrentPermission(), std::forward(f), std::forward(args)...);
+ }
+
+ /**
+ * @brief Move assignment operator.
+ * @param[in] rthread Reference to the thread object.
+ * @return Reference to this object.
+ */
+ secure_thread& operator=(secure_thread&& rthread)
+ {
+ static_cast(*this) = static_cast(rthread);
+ return *this;
+ }
+ };
+ } // namespace core
+}// namespace sdv
+
+/**
+ * @{
+ * @brief Comparison operators
+ * @param[in] e1 First permission
+ * @param[in] e2 Second permission
+ * @return Result of the comparison
+ */
+inline bool operator<(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast(e1) < static_cast(e2); }
+inline bool operator<=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast(e1) <= static_cast(e2); }
+inline bool operator>(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast(e1) > static_cast(e2); }
+inline bool operator>=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast(e1) >= static_cast(e2); }
+/**
+ * @}
+ */
+
+namespace sdv
+{
namespace app
{
/**
@@ -208,11 +742,11 @@ namespace sdv
* @param[in] rssAttribute Name of the attribute.
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
*/
- inline any_t GetAppAttribute(const std::string& rssAttribute)
+ inline any_t GetAppSettingsAttribute(const std::string& rssAttribute)
{
- const IAttributes* ptrAppAttributes = core::GetObject("AppControlService");
- if (!ptrAppAttributes) return {};
- return ptrAppAttributes->Get(rssAttribute);
+ const IParameters* pParameters = core::GetObject("AppSettingsService");
+ if (!pParameters) return {};
+ return pParameters->GetParam(rssAttribute);
}
/**
@@ -221,7 +755,7 @@ namespace sdv
*/
inline bool ConsoleIsSilent()
{
- return GetAppAttribute("console.info_level") == "silent";
+ return GetAppSettingsAttribute("Console.Reporting") == "Silent";
}
/**
@@ -230,7 +764,7 @@ namespace sdv
*/
inline bool ConsoleIsVerbose()
{
- return GetAppAttribute("console.info_level") == "verbose";
+ return GetAppSettingsAttribute("Console.Reporting") == "Verbose";
}
/**
@@ -239,7 +773,7 @@ namespace sdv
*/
inline uint32_t GetAppInstanceID()
{
- return GetAppAttribute("app.instance_id");
+ return GetAppSettingsAttribute("Application.Instance");
}
} // namespace app
@@ -247,64 +781,81 @@ namespace sdv
{
/**
* @brief Create a repository connection to a local server.
- * @param[in] uiInstanceID Optionally the instance ID of the target system to connect to or 0 (default) to connect to the
- * instance identified by app-control.
* @param[in] nRetries Number of retries to connect (optional, default 30, minimum 3).
* @return Returns a smart pointer to the repository proxy. Disconnection takes place when IObjectDestroy::DestroyObject is
* called.
*/
- inline TObjectPtr ConnectToLocalServerRepository(uint32_t uiInstanceID = 0, size_t nRetries = 30)
+ inline TObjectPtr ConnectToLocalServerRepository(size_t nRetries = 30)
{
- com::IClientConnect* pClientConnect = core::GetObject("ConnectionService");
- if (!pClientConnect)
+ // This function works with main, external and maintenance applications.
+ const app::IAppContext* pAppContext = core::GetCore();
+ if (!pAppContext) return {};
+ switch (pAppContext->GetContextType())
{
- if (!app::ConsoleIsSilent())
- std::cerr << "ERROR: Could not access the connection service." << std::endl;
+ case app::EAppContext::main:
+ case app::EAppContext::external:
+ case app::EAppContext::maintenance:
+ break;
+ default:
+ return {};
+ }
+
+ const sdv::app::IAppConnections* pConnections = core::GetObject("AppSettingsService");
+ if (!pConnections) return {};
+ std::string ssConnectionConfig = pConnections->GetConnectionConfig("Default");
+ if (ssConnectionConfig.empty()) return {};
+
+ sdv::core::IRepositoryControl* pRepository = core::GetObject("RepositoryService");
+ if (!pRepository) return {};
+ auto tConnectSvcID = pRepository->CreateObject("ClientConnectService", "ClientDefault", ssConnectionConfig);
+ if (!tConnectSvcID) return {};
+
+ sdv::TInterfaceAccessPtr ptrConnectSvc = core::GetObject(tConnectSvcID);
+ sdv::com::IClientConnect* pClientConnect = ptrConnectSvc.GetInterface();
+ if (!pClientConnect)
+ {
+ pRepository->DestroyObject("ClientDefault");
return {};
}
- // Connect the client to the server and return the server repository interface.
- std::string ssConnectString = R"code([Client]
-Type = "Local"
-)code";
- if (uiInstanceID)
- ssConnectString += "Instance = " + std::to_string(uiInstanceID) + R"code(
-)code";
try
{
// Try to connect (30 times with 1 second in between).
size_t nCnt = 0;
- sdv::TObjectPtr ptrRepository;
- while (!ptrRepository && nCnt < nRetries)
+ sdv::TObjectPtr ptrRemoteRepo;
+ while (!ptrRemoteRepo && nCnt < std::max(nRetries, static_cast(3u)))
{
nCnt++;
- ptrRepository = pClientConnect->Connect(ssConnectString);
- if (!ptrRepository)
- std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ if (pClientConnect->IsConnected() || pClientConnect->Connect())
+ {
+ ptrRemoteRepo = pClientConnect->GetRemoteRepository();
+ break;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
// Return the result
- return ptrRepository;
+ return ptrRemoteRepo;
}
catch (const XAccessDenied& /*rExcept*/)
{
if (!app::ConsoleIsSilent())
std::cout << "Access denied trying to connect to a local repository with server instance ID#" <<
- (uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
+ app::GetAppInstanceID() << "." << std::endl;
return {};
}
catch (const XNotFound& /*rExcept*/)
{
if (!app::ConsoleIsSilent())
std::cout << "Local repository with server instance ID#" <<
- (uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " not found." << std::endl;
+ app::GetAppInstanceID() << " not found." << std::endl;
return {};
}
catch (const XInvalidState& rExcept)
{
if (!app::ConsoleIsSilent())
std::cout << "The local repository with server instance ID#" <<
- (uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " is in an invalid state: " << rExcept.what() <<
+ app::GetAppInstanceID() << " is in an invalid state: " << rExcept.what() <<
std::endl;
return {};
}
@@ -312,12 +863,11 @@ Type = "Local"
{
if (!app::ConsoleIsSilent())
std::cout << "Timeout occurred trying to connect to a local repository with server instance ID#" <<
- (uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
+ app::GetAppInstanceID() << "." << std::endl;
return {};
}
}
-
- } // namespace core
+ } // namespace com
} // namespace sdv
#endif // !defined LOCAL_SERVICE_ACCESS_H
\ No newline at end of file
diff --git a/export/support/param_impl.h b/export/support/param_impl.h
index 7344e5a..88f0ab4 100644
--- a/export/support/param_impl.h
+++ b/export/support/param_impl.h
@@ -435,12 +435,14 @@ namespace sdv
* @tparam TInfoConstruct The type of the variables that are provided to the constructor function of the parameter
* information.
* @param[in] rtVar Reference to the parameter variable.
+ * @param[in] bReadOnly When set, the parameter is read-only (even when writable) and will not be initialized.
* @param[in] bLockable When set, the parameter is lockable. Only use with writable parameters.
- * @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable parameters.
+ * @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable
+ * parameters.
* @param[in] tConstruct The construct function arguments.
*/
template
- CParamValue(TVar& rtVar, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);
+ CParamValue(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);
/**
* @brief Set a value. Overload of CParamGuardian::Set.
@@ -993,7 +995,7 @@ namespace sdv
} \
std::vector> vecParamInfo; \
[[maybe_unused]] uint32_t uiFlags = 0; \
- [[maybe_unused]] std::string ssGroup; \
+ [[maybe_unused]] std::string ssGroup; \
[[maybe_unused]] bool bLockable = false;
/**
@@ -1107,8 +1109,9 @@ namespace sdv
} \
else \
{ \
- std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
- default_val, unit_string, ssGroup, description_string, uiFlags); \
+ std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, \
+ uiFlags & static_cast(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
+ unit_string, ssGroup, description_string, uiFlags); \
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
}
@@ -1126,7 +1129,7 @@ namespace sdv
* @param description_string The description of the parameter.
*/
#define SDV_PARAM_NUMBER_ENTRY(var, name_string, default_val, low_limit, high_limit, unit_string, description_string) \
- { \
+ { \
auto prLowLimit = sdv::internal::SLowerLimit() low_limit; \
sdv::any_t anyLower; \
if (prLowLimit.second != sdv::internal::ELimitType::no_limit) anyLower = prLowLimit.first; \
@@ -1144,8 +1147,9 @@ namespace sdv
} \
else \
{ \
- std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, \
- name_string, default_val, anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper, \
+ std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, \
+ uiFlags & static_cast(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
+ anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper, \
prHighLimit.second != sdv::internal::ELimitType::up_to_limit, unit_string, ssGroup, description_string, \
uiFlags); \
if (ptrParamInfo)vecParamInfo.push_back(std::move(ptrParamInfo)); \
@@ -1181,8 +1185,9 @@ namespace sdv
} \
else \
{ \
- std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
- default_val, pattern_string, unit_string, ssGroup, description_string, uiFlags); \
+ std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, \
+ uiFlags & static_cast(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
+ pattern_string, unit_string, ssGroup, description_string, uiFlags); \
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
}
@@ -1213,8 +1218,9 @@ namespace sdv
} \
else \
{ \
- std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
- default_val, sdv::internal::GetLabelMapHelper().GetLabelMap(), ssGroup, description_string, uiFlags); \
+ std::shared_ptr ptrParamInfo = pObject->RegisterParameter(pObject->var, \
+ uiFlags & static_cast(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
+ sdv::internal::GetLabelMapHelper().GetLabelMap(), ssGroup, description_string, uiFlags); \
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
}
@@ -1238,11 +1244,12 @@ namespace sdv
std::vector> vecParamInfoMember; \
if constexpr (bStatic) \
{ \
- vecParamInfoMember = sdv::internal::SMemberMap::BuildStatic(); \
+ vecParamInfoMember = sdv::internal::SMemberMap>::BuildStatic(); \
} \
else \
{ \
- auto ptrMemberMap = std::make_shared>(pObject->member, pObject); \
+ auto ptrMemberMap = \
+ std::make_shared>>(pObject->member, pObject); \
if (ptrMemberMap) \
{ \
ptrMemberMap->BuildMap(); \
@@ -1388,13 +1395,15 @@ namespace sdv
* @tparam TVar Type of the variable.
* @tparam TConstruct The arguments for the parameter info construct function.
* @param[in] rtVar Reference to the parameter.
+ * @param[in] bReadOnly When set, the parameter is read only and will not be initialized.
* @param[in] bLockable When set, the parameter is lockable. Only use with writable parameters.
* @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable parameters.
* @param[in] tConstruct The construct function arguments.
* @return Smart pointer to the parameter information structure.
*/
template
- std::shared_ptr RegisterParameter(TVar& rtVar, bool bLockable, bool bAutoDirty, TConstruct... tConstruct);
+ std::shared_ptr RegisterParameter(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty,
+ TConstruct... tConstruct);
/**
* @brief Register a member parameter map into this parameter map.
diff --git a/export/support/param_impl.inl b/export/support/param_impl.inl
index 83a6d67..9da6136 100644
--- a/export/support/param_impl.inl
+++ b/export/support/param_impl.inl
@@ -412,13 +412,14 @@ namespace sdv
template
template
- inline CParamValue::CParamValue(TVar& rtVar, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct) :
+ inline CParamValue::CParamValue(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty,
+ TInfoConstruct... tConstruct) :
CParamGuardian(bLockable, bAutoDirty, rtVar, tConstruct...), m_rtVar(rtVar)
{
// Assign the default value
if constexpr (!CSdvParamInfo::TypeIsReadOnly())
{
- m_rtVar = DefaultVal().get();
+ if (!bReadOnly) m_rtVar = DefaultVal().get();
UpdateDirty(DefaultVal());
ResetDirty();
}
@@ -678,10 +679,10 @@ namespace sdv
}
template
- inline std::shared_ptr CSdvParamMap::RegisterParameter(TVar& rtVar, bool bLockable, bool bAutoDirty,
- TConstruct... tConstruct)
+ inline std::shared_ptr CSdvParamMap::RegisterParameter(TVar& rtVar, bool bReadOnly, bool bLockable,
+ bool bAutoDirty, TConstruct... tConstruct)
{
- auto ptrParam = std::make_shared>(rtVar, bLockable, bAutoDirty, tConstruct...);
+ auto ptrParam = std::make_shared>(rtVar, bReadOnly, bLockable, bAutoDirty, tConstruct...);
m_vecParamMapRegistration.push_back(SParamRegistration(ptrParam));
return ptrParam;
}
diff --git a/export/support/pssup.inl b/export/support/pssup.inl
index ded58f0..997e76c 100644
--- a/export/support/pssup.inl
+++ b/export/support/pssup.inl
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
namespace serdes
{
@@ -378,7 +379,25 @@ namespace sdv
inline CRawDataBypass& GetRawDataBypass()
{
+#if defined __GNUC__ && defined _WIN32
+ // https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/610009
+ // In MINGW GCC implementation of thread_local, there is an issue with complex classes being used after the destruction.
+ // This is caused by an architectural bug (https://github.com/msys2/MINGW-packages/issues/2519) causing the emutls (GCC
+ // Emulated TLS) managing the memory allocation to be executed before the __cxa_thread_exit, the thread cleanup callback
+ // of Windows. The solution is to use trivial data only (pointer, reference, integers, etc.). A workaround is
+ // implemented to use a reference of the permission list and map instead of an instance to the list and map.
+ static auto fnCreateBypass = []() -> CRawDataBypass&
+ {
+ static std::mutex mtx;
+ static std::list lstRawDataBypasses;
+ std::unique_lock lock(mtx);
+ lstRawDataBypasses.resize(lstRawDataBypasses.size() + 1);
+ return lstRawDataBypasses.back();
+ };
+ thread_local static CRawDataBypass& bypass = fnCreateBypass();
+#else
thread_local static CRawDataBypass bypass;
+#endif
return bypass;
}
diff --git a/export/support/sdv_core.h b/export/support/sdv_core.h
index 470f517..d285bac 100644
--- a/export/support/sdv_core.h
+++ b/export/support/sdv_core.h
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#ifdef _WIN32
// Resolve conflict
@@ -59,6 +60,8 @@
#error OS is not supported!
#endif
+#include "simple_toml.h"
+
namespace sdv
{
/**
@@ -148,7 +151,36 @@ namespace sdv{
{
/**
* @brief The SDV core loader
- */
+ * @details The SDV core loader class searches for the core library and does the first startup. The core library uses
+ * the following environment variables to identify its location:
+ * - SDV_FRAMEWORK_RUNTIME directs to the Vehicle API core location.
+ * - SDV_COMPONENT_INSTALL directs to the location of the component installations.
+ * - SDV_FRAMEWORK_DEV_TOOLS directs to the location of the development tools used during the build process of SDV
+ * components.
+ * - SDV_FRAMEWORK_DEV_INCLUDE directs to the header file location to allow building components for use with the
+ * Vehicle API framework.
+ *
+ * The SDV core loader supports different core stacks to coexist. For this there is a location procedure for the core
+ * systems:
+ * 1. Check for a "sdv_core_reloc.toml" file that contain one or more paths to the core system. The paths defined in the
+ * file override the global environment variables for this application and all child applications.
+ * 2. Check for the environment variables. If the SDV_FRAMEWORK_RUNTIM variable is set, it is used to extract all other
+ * variables as well, if not set.
+ * 3. If no variable is set, use the location of the EXE as core location. This might work in some situations if the
+ * path variable has been set properly.
+ *
+ * If none of the above strategies work, the core cannot be loaded.
+ *
+ * The "sdv_core_reloc.toml" file has the following format:
+ * @code
+ * [CoreLocation]
+ * Version = 100 # Version; currently supported 100 for version 1.0
+ * Runtime = ""
+ * Install = "" # Typically identical to runtime directory
+ * DevTools = "" # Typically identical to runtime directory
+ * Include = "" # Typically in the include subdirectory
+ * @endcode
+ */
class CSDVCoreLoader
{
public:
@@ -189,77 +221,50 @@ namespace sdv{
{
if (m_bInit) return; // Prevent trying to load again.
m_bInit = true;
- bool bRelocFileError = false;
- std::string ssRelocFileInfo = "";
std::string ssEnvironmentInfo = "";
- // Check for the executable directory
- std::filesystem::path pathCoreLib;
- if (std::filesystem::exists(GetExecDirectory() / "core_services.sdv"))
- pathCoreLib = GetExecDirectory() / "core_services.sdv";
+ // Step 1: check for the "sdv_core_reloc.toml"
+ ProcessRelocationFile();
- if (pathCoreLib.empty())
- {
- if (std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml"))
- {
- // Check for the library in the relocation directory
- auto relocFolder = GetRelocationPath();
- if (!relocFolder.empty())
- {
- auto coreLibFolder = std::filesystem::path(relocFolder) / "core_services.sdv";
- if (coreLibFolder.is_relative())
- coreLibFolder = (GetExecDirectory() / coreLibFolder).lexically_normal();
-
- if (std::filesystem::exists(coreLibFolder))
- pathCoreLib = coreLibFolder;
- }
- if (pathCoreLib.empty())
- {
- bRelocFileError = true; // we found the file but not the core library, we must run into an error
- ssRelocFileInfo = "Error: Invalid \"sdv_core_reloc.toml\" file found (but no core library), it contains: " + relocFolder;
- }
- }
- }
-
- if (pathCoreLib.empty())
- {
+ // Step 2: check for environment variables (either set globally or overwritten by the sdv_core_reloc.toml).
#ifdef _WIN32
- std::wstring ssPathCoreTemp(32768, '\0');
- GetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", ssPathCoreTemp.data(), static_cast(ssPathCoreTemp.size()));
- ssPathCoreTemp.resize(wcsnlen(ssPathCoreTemp.c_str(), ssPathCoreTemp.size()));
- if (!ssPathCoreTemp.empty())
- {
- pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
+ std::wstring ssPathCoreTemp(32768, '\0');
+ GetEnvironmentVariable(
+ L"SDV_FRAMEWORK_RUNTIME", ssPathCoreTemp.data(), static_cast(ssPathCoreTemp.size()));
+ ssPathCoreTemp.resize(wcsnlen(ssPathCoreTemp.c_str(), ssPathCoreTemp.size()));
+ if (!ssPathCoreTemp.empty())
+ {
+ m_pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
#else
- std::string ssPathCoreTemp = std::getenv("SDV_FRAMEWORK_RUNTIME") ? std::getenv("SDV_FRAMEWORK_RUNTIME") : "";
- if (!ssPathCoreTemp.empty())
- {
- pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
+ std::string ssPathCoreTemp = std::getenv("SDV_FRAMEWORK_RUNTIME") ? std::getenv("SDV_FRAMEWORK_RUNTIME") : "";
+ if (!ssPathCoreTemp.empty())
+ {
+ m_pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
#endif
- if (pathCoreLib.is_relative())
- pathCoreLib = (GetExecDirectory() / pathCoreLib).lexically_normal();
+ if (m_pathCoreLib.is_relative())
+ m_pathCoreLib = (GetExecDirectory() / m_pathCoreLib).lexically_normal();
- if (!pathCoreLib.empty())
- ssEnvironmentInfo = "System environment path: " + pathCoreLib.generic_string();
- }
}
- // Depend on system path to find the library
- if (pathCoreLib.empty())
- pathCoreLib = "core_services.sdv";
-
- // Open the library only if there is no or a valid 'sdv_core_reloc.toml' file
- if (!bRelocFileError)
+ // Step 3: check for the executable directory or otherwise check globally
+ if (m_pathCoreLib.empty())
{
+ if (std::filesystem::exists(GetExecDirectory() / "core_services.sdv"))
+ m_pathCoreLib = GetExecDirectory() / "core_services.sdv";
+ else
+ m_pathCoreLib = "core_services.sdv";
+ }
+
+ ssEnvironmentInfo = "System environment path: " + m_pathCoreLib.generic_string();
+
#ifdef _WIN32
- SetErrorMode(SEM_FAILCRITICALERRORS);
- m_tModule = reinterpret_cast(LoadLibraryW(pathCoreLib.native().c_str()));
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+ m_tModule = reinterpret_cast(LoadLibraryW(m_pathCoreLib.native().c_str()));
#elif defined __unix__
- m_tModule = reinterpret_cast(dlopen(pathCoreLib.native().c_str(), RTLD_LAZY));
+ m_tModule = reinterpret_cast(dlopen(m_pathCoreLib.native().c_str(), RTLD_LAZY));
#else
#error OS is not supported!
#endif
- }
if (!m_tModule)
{
@@ -275,16 +280,12 @@ namespace sdv{
#else
#error OS is not supported!
#endif
- if (ssRelocFileInfo.empty() && ssEnvironmentInfo.empty())
- std::cerr << "No environment variable set and no realocation file found." << std::endl;
- if (!ssRelocFileInfo.empty())
- std::cerr << ssRelocFileInfo << std::endl;
if (!ssEnvironmentInfo.empty())
std::cerr << ssEnvironmentInfo << std::endl;
-
- std::cerr << "Could not load \"core_services.sdv\" library";
- if (!ssError.empty()) std::cerr << ": " << ssError;
- std::cerr << std::endl;
+ m_ssErrMsg = "Could not load \"core_services.sdv\" library";
+ if (!ssError.empty())
+ m_ssErrMsg += ": " + ssError;
+ std::cerr << m_ssErrMsg << std::endl;
return;
}
@@ -301,7 +302,8 @@ namespace sdv{
#endif
if (!fnSDVCore)
{
- std::cerr << "The library \"core_services.sdv\" doesn't expose the SDVCore function." << std::endl;
+ m_ssErrMsg = "The library \"core_services.sdv\" doesn't expose the SDVCore function.";
+ std::cerr << m_ssErrMsg << std::endl;
return;
}
@@ -311,7 +313,8 @@ namespace sdv{
m_pCore = fnSDVCore();
if (!m_pCore)
{
- std::cerr << "The library \"core_services.sdv\" doesn't provide a valid interface." << std::endl;
+ m_ssErrMsg = "The library \"core_services.sdv\" doesn't provide a valid interface.";
+ std::cerr << m_ssErrMsg << std::endl;
return;
}
}
@@ -321,7 +324,6 @@ namespace sdv{
*/
operator TInterfaceAccessPtr() const { return m_pCore; }
- private:
/**
* @brief Get the directory of the executable.
* @return Path to the directory.
@@ -346,86 +348,170 @@ namespace sdv{
}
/**
- * @brief Get the folder path in the file 'sdv_core_reloc.toml'.
- * @return Path content, empty string if not found.
- */
- static std::string GetRelocationPath()
+ * @brief Get the path to the core library.
+ * @return Returns a reference to the path to the core library.
+ */
+ const std::filesystem::path& GetCoreLibPath() const
{
- if (std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml"))
- {
- std::ifstream fstream(GetExecDirectory() / "sdv_core_reloc.toml");
- std::string ssLine;
- while (std::getline(fstream, ssLine))
- {
- size_t nPos = 0;
- auto fnSkipWhitespace = [&]() { while (std::isspace(ssLine[nPos])) nPos++; };
- fnSkipWhitespace();
- if (ssLine[nPos] == '#') continue; // Rest of the line is comments
- if (ssLine.substr(nPos, 9) != "directory") continue; // not the keq of interest: skip line
- nPos += 9;
- fnSkipWhitespace();
- if (ssLine[nPos] != '=')
- {
- std::cout << "Error in \"sdv_core_reloc.toml\": expecting assignment character '=' following"
- " keyword 'directory'." << std::endl;
- break;
- }
- nPos++;
- fnSkipWhitespace();
- if (ssLine[nPos] != '\"')
- {
- std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
- " a string begin'." << std::endl;
- break;
- }
- nPos++;
- size_t nStart = nPos;
- while (nPos < ssLine.length() && ssLine[nPos] != '\"')
- {
- // Check for escape character
- if (ssLine[nPos] == '\\') nPos++;
-
- // Skip character
- nPos++;
- }
- if (nPos >= ssLine.length() || ssLine[nPos] != '\"')
- {
- std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
- " a string end'." << std::endl;
- break;
- }
- std::string ssDirectory = ssLine.substr(nStart, nPos - nStart);
- while (ssDirectory.empty())
- {
- std::cout << "Error in \"sdv_core_reloc.toml\": expecting a valid value following the assignment"
- " of the 'directory' key." << std::endl;
- break;
- }
-
- return ssDirectory;
- }
- }
- return "";
+ return m_pathCoreLib;
}
- bool m_bInit = false; ///< Is the loader initialized?
- core::TModuleID m_tModule = 0; ///< Module ID
- IInterfaceAccess* m_pCore = nullptr; ///< Pointer to the core services.
+ /**
+ * @brief Has loaded successfully?
+ * @return Returns whether loading was successful.
+ */
+ bool HasLoaded() const
+ {
+ return m_bInit && m_tModule && m_pCore;
+ }
+
+ /**
+ * @brief Get the error message if loading was unsuccessful.
+ * @return Returns the a reference to the string containing the error message or an empty string if not available.
+ */
+ const std::string& GetErrorMsg() const
+ {
+ return m_ssErrMsg;
+ }
+
+ private:
+ /**
+ * @brief Check for the 'sdv_core_reloc.toml' file containing the information about core relocation.
+ * @details Set the environment variables following the information from the core relocation file.
+ */
+ static void ProcessRelocationFile()
+ {
+ if (!std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml")) return;
+
+ std::ifstream fstream(GetExecDirectory() / "sdv_core_reloc.toml");
+ if (!fstream.is_open()) return;
+
+ std::stringstream sstreamContent;
+ sstreamContent << fstream.rdbuf();
+ fstream.close();
+
+ try
+ {
+ sdv::toml::simple_parser::CParser parser(sstreamContent.str());
+ if (parser.Root().GetDirect("CoreLocation.Version").GetValue() != SDVFrameworkInterfaceVersion)
+ {
+ std::cerr << "Invalid version in sdv_core_reloc.toml" << std::endl;
+ return; // Version not supported
+ }
+
+ const auto& sRuntimeNode = parser.Root().GetDirect("CoreLocation.Runtime");
+ if (sRuntimeNode)
+ {
+ // Note: since the system might load multiple executables and the path is relative to this executable,
+ // but maybe not to another executable, create an absolute path before assigning the environment
+ // variable.
+ std::filesystem::path pathRuntime = sRuntimeNode.GetValue();
+ if (pathRuntime.is_relative())
+ pathRuntime = (GetExecDirectory() / pathRuntime).lexically_normal();
+#ifdef _WIN32
+ // NOTE: In windows there are two environment variables which need to be updated.
+ std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", pathRuntime.native().c_str());
+ std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_RUNTIME=") + pathRuntime.native()).c_str());
+#elif defined __unix__
+ std::ignore = setenv("SDV_FRAMEWORK_RUNTIME", pathRuntime.generic_u8string().c_str(), 1);
+#else
+#error The OS is not supported!
+#endif
+ }
+
+ const auto& sInstallNode = parser.Root().GetDirect("CoreLocation.Install");
+ if (sInstallNode)
+ {
+ // Note: since the system might load multiple executables and the path is relative to this executable,
+ // but maybe not to another executable, create an absolute path before assigning the environment
+ // variable.
+ std::filesystem::path pathInstall = sInstallNode.GetValue();
+ if (pathInstall.is_relative())
+ pathInstall = (GetExecDirectory() / pathInstall).lexically_normal();
+#ifdef _WIN32
+ // NOTE: In windows there are two environment variables which need to be updated.
+ std::ignore = SetEnvironmentVariable(L"SDV_COMPONENT_INSTALL", pathInstall.native().c_str());
+ std::ignore = _wputenv((std::wstring(L"SDV_COMPONENT_INSTALL=") + pathInstall.native()).c_str());
+#elif defined __unix__
+ std::ignore = setenv("SDV_COMPONENT_INSTALL", pathInstall.generic_u8string().c_str(), 1);
+#else
+#error The OS is not supported!
+#endif
+ }
+
+ const auto& sDevToolsNode = parser.Root().GetDirect("CoreLocation.DevTools");
+ if (sDevToolsNode)
+ {
+ // Note: since the system might load multiple executables and the path is relative to this executable,
+ // but maybe not to another executable, create an absolute path before assigning the environment
+ // variable.
+ std::filesystem::path pathDevTools = sDevToolsNode.GetValue();
+ if (pathDevTools.is_relative())
+ pathDevTools = (GetExecDirectory() / pathDevTools).lexically_normal();
+#ifdef _WIN32
+ // NOTE: In windows there are two environment variables which need to be updated.
+ std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_DEV_TOOLS", pathDevTools.native().c_str());
+ std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_DEV_TOOLS=") + pathDevTools.native()).c_str());
+#elif defined __unix__
+ std::ignore = setenv("SDV_FRAMEWORK_DEV_TOOLS", pathDevTools.generic_u8string().c_str(), 1);
+#else
+#error The OS is not supported!
+#endif
+ }
+
+ const auto& sIncludeNode = parser.Root().GetDirect("CoreLocation.Include");
+ if (sIncludeNode)
+ {
+ // Note: since the system might load multiple executables and the path is relative to this executable,
+ // but maybe not to another executable, create an absolute path before assigning the environment
+ // variable.
+ std::filesystem::path pathInclude = sIncludeNode.GetValue();
+ if (pathInclude.is_relative())
+ pathInclude = (GetExecDirectory() / pathInclude).lexically_normal();
+#ifdef _WIN32
+ // NOTE: In windows there are two environment variables which need to be updated.
+ std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_DEV_INCLUDE", pathInclude.native().c_str());
+ std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_DEV_INCLUDE=") + pathInclude.native()).c_str());
+#elif defined __unix__
+ std::ignore = setenv("SDV_FRAMEWORK_DEV_INCLUDE", pathInclude.generic_u8string().c_str(), 1);
+#else
+#error The OS is not supported!
+#endif
+ }
+ }
+ catch (const std::exception&)
+ {}
+ }
+
+ bool m_bInit = false; ///< Is the loader initialized?
+ core::TModuleID m_tModule = 0; ///< Module ID
+ IInterfaceAccess* m_pCore = nullptr; ///< Pointer to the core services.
+ std::filesystem::path m_pathCoreLib; ///< Path to the core library.
+ std::string m_ssErrMsg; ///< Error message for failed loading.
};
} // namespace internal
#ifndef NO_SDV_CORE_FUNC
/**
- * @brief Access to the core.
- * @return Smart pointer to the core services interface.
+ * @brief Access to the core loader.
+ * @return Reference to the one core loader instance.
*/
- inline TInterfaceAccessPtr GetCore()
+ inline internal::CSDVCoreLoader& GetCoreLoader()
{
static internal::CSDVCoreLoader core;
core.Load();
return core;
}
+ /**
+ * @brief Access to the core interfaces.
+ * @return Smart pointer to the core services interfaces.
+ */
+ inline TInterfaceAccessPtr GetCore()
+ {
+ return GetCoreLoader();
+ }
+
/**
* @brief Access to specific interface of the core.
* @tparam TInterface Type of interface to return.
diff --git a/export/support/signal_support.h b/export/support/signal_support.h
index 2485105..0e4d490 100644
--- a/export/support/signal_support.h
+++ b/export/support/signal_support.h
@@ -546,10 +546,10 @@ namespace sdv
if (m_ptrValue) m_ptrValue->Receive(anyVal);
}
- CDispatchService& m_rDispatch; ///< Reference to the dispatch service.
- std::function m_funcSignalReceive; ///< Receive signal data - callback function.
- IInterfaceAccess* m_pSubscription = nullptr; ///< Cookie received by adding an receive subscription.
- std::unique_ptr m_ptrValue; ///< Value to update instead of a callback function.
+ CDispatchService& m_rDispatch; ///< Reference to the dispatch service.
+ std::function m_funcSignalReceive; ///< Receive signal data - callback function.
+ IInterfaceAccess* m_pSubscription = nullptr; ///< Cookie received by adding a subscription.
+ std::unique_ptr m_ptrValue; ///< Value to update instead of callback func.
};
/**
diff --git a/export/support/simple_toml.h b/export/support/simple_toml.h
new file mode 100644
index 0000000..89db338
--- /dev/null
+++ b/export/support/simple_toml.h
@@ -0,0 +1,1010 @@
+#pragma once
+
+#include
+#include
+#include
+#include