From cfe756b436638ca21b06e722dc2adc0f5cb23529 Mon Sep 17 00:00:00 2001 From: Stephan Muench Date: Mon, 13 Oct 2025 10:50:59 +0200 Subject: [PATCH 1/2] docs: add design for C++ abstraction layer API to be used by user code --- ...ction_layer_api_for_user_applications.puml | 444 ++++++++++++++++++ ...action_layer_api_for_user_applications.svg | 1 + 2 files changed, 445 insertions(+) create mode 100755 docs/design/cpp_abstraction_layer_api_for_user_applications.puml create mode 100644 docs/design/cpp_abstraction_layer_api_for_user_applications.svg diff --git a/docs/design/cpp_abstraction_layer_api_for_user_applications.puml b/docs/design/cpp_abstraction_layer_api_for_user_applications.puml new file mode 100755 index 0000000..2f3755f --- /dev/null +++ b/docs/design/cpp_abstraction_layer_api_for_user_applications.puml @@ -0,0 +1,444 @@ +@startuml CppAbstractionLayerAPIForDiagnosticServices + +!theme plain +skinparam classAttributeIconSize 0 +skinparam classFontSize 11 +skinparam packageStyle rectangle + +package "Design Goals" as DesignGoals {} +package "see cpp_abstraction_layer_api_for_user_applications.md" as DesignGoals.Reference {} + +package "score::result" { + entity "using ErrorCode = std::int32_t" as SCORE_ErrorCode +} + +package "mw::diag" { + enum ErrorCode { + kUnknown + kInternalError + } + + entity "Result" as DiagResult { + alias for `score::Result` + } + + entity ByteSequence { + <> + ByteSequence = std::span + } + + entity ByteVector { + <> + ByteVector = std::pmr::vector + } + + abstract class DiagnosticServicesCollection { + no public methods are defined since lifetime control of contained services is the only goal of this class + } +} + +package "mw::diag::sovd" { + class "Error" as SOVDError { + sovd_error : std::pmr::string + vendor_error : std::pmr::string + vendor_message : std::pmr::string + } + + class "Result" as SOVDResult { + alias for `score::details::expected` + } + + class TranslationIdentifier {} + class DataCategoryIdentifier {} + class DataGroupIdentifier {} + class DataGroupShortDesc {} + class JsonSchemaView {} + + enum DataCategoryIdentifiers { + kIdentification // corresponds to SOVD 'identData' + kMeasurement // corresponds to SOVD 'currentData' + kParameter // corresponds to SOVD 'storedData' + kSysInfo // corresponds to SOVD 'sysInfo' + } + + enum OperationInvocationPolicy { + kPerformsSynchronousInvocation + kRequiresIndividualAsyncInvocations + kSupportsConcurrentAsyncInvocations + } + + enum ProximityProof { + kRequired + kNotRequired + } + + enum "DiagnosticEntity::Kind" as DiagnosticEntityKind { + kApplication + } + + class "DiagnosticEntity::Mode" as DiagnosticEntityMode { + +id : std::pmr::string + +name : std::pmr::string + +translation_id : std::optional + +values : std::pmr::vector + } + + class DiagnosticEntity { + using Identifier = std::pmr::string + .. + #TO BE CLARIFIED: are these two required here or will locking be handled completely by SOVD Server instead? + #{abstract} Lock() : mw::diag::sovd::Result + #{abstract} Unlock() : mw::diag::sovd::Result + .. + {abstract} GetKind() : DiagnosticEntity::Kind + .. + {abstract} GetSupportedModes() : mw::diag::sovd::Result> + {abstract} ApplyMode(mode_id : std::pmr::string, mode_value : std::pmr::string, expiration_timeout : std::optional) : mw::diag::sovd::Result + } + + class "DiagnosticServicesCollection" as SOVDDiagnosticServicesCollection { + +explicit DiagnosticServicesCollection(DiagnosticEntity&, std::pmr::memory_resource&) + ~DiagnosticServicesCollection() + } + note right: upon destruction, will release all functionality as well as\nregistered services of the referenced DiagnosticEntity from\nthe underlying binding implementation + + class "DiagnosticServicesCollectionBuilder" as SOVDDiagnosticServicesCollectionBuilder { + +using Identifier = std::string_view + + +explicit DiagnosticServicesCollectionBuilder(DiagnosticEntity&, std::pmr::memory_resource&) + + +With(Identifier, JsonSchemaView, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder& + +With(Identifier, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder& + +With(Identifier, JsonSchemaView, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder& + +With(DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder& + +With(DataGroupIdentifier, DataGroupShortDesc, std::optional, DataCategoryIdentifier, Args&&...) : DiagnosticServicesCollectionBuilder& + +With(Identifier, OperationInvocationPolicy, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder& + + .. final step .. + +Build() : mw::diag::Result> + } +} + +package "mw::diag::sovd" { + class DiagnosticRequest { + +explicit DiagnosticRequest(std::pmr::memory_resource&) + + +<> + -- + -headers_ : std::pmr::unordered_map + -proximity_response_: std::optional + -data_ : JSON + } + + class DiagnosticReply { + +explicit DiagnosticReply(std::pmr::memory_resource&) + + +<> + -- + -headers_ : std::pmr::unordered_map + } + + class ProximityChallenge { + +challenge : std::pmr::string + +valid_until : time_point + } + + class JsonDataReply { + +explicit JsonDataReply(std::pmr::memory_resource&) + + +<> + -- + -data_ : JSON -> json data created from content of deriving classes + } + + interface ReadOnlyDataResource { + API definition for read-only SOVD data resources + + {abstract} Get() : mw::diag::sovd::Result + } + + interface WritableDataResource { + API definition for writable SOVD data resources + + {abstract} Put(DiagnosticRequest) : mw::diag::sovd::Result + } + + interface DataResource { + API definition for SOVD data resources + } + + enum OperationExecutionStatus { + kFailed + kRunning + kStopped + kCompleted + } + + class OperationInfoReply { + +explicit OperationInfoReply(std::pmr::memory_resource&) + + +<> + -- + -supported_modes_ : std::pmr::vector + } + + class OperationStatusReply { + +explicit OperationStatusReply(std::pmr::memory_resource&) + + +<> + -- + -capability_ : std::pmr::string + -parameters_ : JSON + } + + class ExecuteOperationReply { + +explicit ExecuteOperationReply(std::pmr::memory_resource&) + } + + interface Operation { + API definition for SOVD operations + + .. standard SOVD capabilities .. + {abstract} Info(DiagnosticRequest) : mw::diag::sovd::Result + {abstract} Status(DiagnosticRequest) : mw::diag::sovd::Result + {abstract} Execute(DiagnosticRequest) : mw::diag::sovd::Result + {abstract} Resume(DiagnosticRequest) : mw::diag::sovd::Result + {abstract} Reset(DiagnosticRequest) : mw::diag::sovd::Result + {abstract} Stop(DiagnosticRequest) : mw::diag::sovd::Result + + .. OEM-specific capabilities .. + .. only to be overridden by deriving classes if required .. + {abstract} Handle(DiagnosticRequest) : mw::diag::sovd::Result + } +} + +package "mw::diag::uds" { + interface ReadDataByIdentifier { + API definition for UDS Service 'Read Data by Identifier' + + {abstract} Read() : score::Result + } + + interface WriteDataByIdentifier { + API definition for UDS Service 'Write Data by Identifier' + + {abstract} Write(ByteSequence) : mw::diag::Result + } + + abstract class DataIdentifier { + <> + } + + interface RoutineControl { + API definition for UDS RoutineControl + + {abstract} Start(ByteSequence) : Result + {abstract} Stop(ByteSequence) : Result + {abstract} RequestResults(ByteSequence) : Result + } + + interface UDSService { + API definition for a generic UDS Service + + {abstract} HandleMessage(ByteSequence) : score::Result + } + + class "SerializedReadDataByIdentifier" as SerializedReadDataByIdentifier { + {abstract} Read() : Result {override} + } + + class "SerializedWriteDataByIdentifier" as SerializedWriteDataByIdentifier { + {abstract} Write(ByteSequence) : mw::diag::Result {override} + } + + class "SerializedDataByIdentifier" as SerializedDataByIdentifier { + {abstract} Read() : Result {override} + {abstract} Write(ByteSequence) : mw::diag::Result {override} + } + + class "SerializedRoutineControl" as SerializedRoutineControl { + <