diff --git a/examples/template/config.toml b/examples/template/config.toml index 3d7eb26..2fb392c 100644 --- a/examples/template/config.toml +++ b/examples/template/config.toml @@ -33,3 +33,13 @@ element_types = "SwComponentType" suffix_filters = ["_Implementation"] +[behavior] + background_event_prefix = "BT_" + data_receive_error_event_prefix = "DRET_" + data_receive_event_prefix = "DRT_" + init_event_prefix = "IT_" + operation_invoked_event_prefix = "OIT_" + swc_mode_manager_error_event_prefix = "MMET_" + swc_mode_switch_event_prefix = "MST_" + timing_event_prefix = "TMT_" + diff --git a/examples/template/demo_system/component.py b/examples/template/demo_system/component.py index ba7601e..c2457cc 100644 --- a/examples/template/demo_system/component.py +++ b/examples/template/demo_system/component.py @@ -5,25 +5,35 @@ import autosar.xml.element as ar_element +import autosar.xml.enumeration as ar_enum import autosar.xml.workspace as ar_workspace from . import factory, portinterface, constants NAMESPACE = "Default" -def create_ReceiverComponent(_0: ar_element.Package, +def create_ReceiverComponent(package: ar_element.Package, workspace: ar_workspace.Workspace, deps: dict[str, ar_element.ARElement] | None, **_1) -> ar_element.ApplicationSoftwareComponentType: """ - Create Receiver component type + Receiver ports: + - EngineSpeed + - VehicleSpeed + Client ports: + - FreeRunningTimer """ timer_interface = deps[portinterface.FreeRunningTimer_I.ref(workspace)] vehicle_speed_interface = deps[portinterface.VehicleSpeed_I.ref(workspace)] engine_speed_interface = deps[portinterface.EngineSpeed_I.ref(workspace)] + ecu_mode_interface = deps[portinterface.EcuM_CurrentMode_I.ref(workspace)] engine_speed_init = deps[constants.EngineSpeed_IV.ref(workspace)] vehicle_speed_init = deps[constants.VehicleSpeed_IV.ref(workspace)] - swc = ar_element.ApplicationSoftwareComponentType("ReceiverComponent") + swc_name = "ReceiverComponent" + swc = ar_element.ApplicationSoftwareComponentType(swc_name) + package.append(swc) + swc.create_require_port("EcuM_CurrentMode", ecu_mode_interface, com_spec={"enhanced_mode_api": False, + "supports_async": False}) swc.create_require_port("EngineSpeed", engine_speed_interface, com_spec={"init_value": engine_speed_init.ref(), "alive_timeout": 0, "enable_update": False, @@ -37,30 +47,48 @@ def create_ReceiverComponent(_0: ar_element.Package, "handle_never_received": False }) swc.create_require_port("FreeRunningTimer", timer_interface) - swc.create_internal_behavior() + init_runnable_name = swc_name + '_Init' + periodic_runnable_name = swc_name + '_Run' + behavior = swc.create_internal_behavior() + behavior.create_runnable(init_runnable_name) + behavior.create_runnable(periodic_runnable_name) + behavior.create_swc_mode_mode_switch_event(init_runnable_name, + "EcuM_CurrentMode/RUN", + ar_enum.ModeActivationKind.ON_ENTRY) + behavior.create_timing_event(periodic_runnable_name, 20.0 / 1000) return swc -def create_TimerComponent(_0: ar_element.Package, +def create_TimerComponent(package: ar_element.Package, workspace: ar_workspace.Workspace, deps: dict[str, ar_element.ARElement] | None, - **_1) -> ar_element.ApplicationSoftwareComponentType: + **_0) -> ar_element.ApplicationSoftwareComponentType: """ Create TimerComponent component type """ timer_interface = deps[portinterface.FreeRunningTimer_I.ref(workspace)] swc = ar_element.ApplicationSoftwareComponentType("TimerComponent") + package.append(swc) swc.create_provide_port("FreeRunningTimer", timer_interface, com_spec={"GetTime": {"queue_length": 1}, "IsTimerElapsed": {"queue_length": 1} }) - swc.create_internal_behavior() + behavior = swc.create_internal_behavior() + init_runnable_name = swc.name + "_Init" + get_time_runnable_name = swc.name + "_GetTime" + timer_elapsed_runnable_name = swc.name + "_IsTimerElapsed" + behavior.create_runnable(init_runnable_name) + behavior.create_runnable(get_time_runnable_name, reentrancy_level=ar_enum.ReentrancyLevel.NON_REENTRANT) + behavior.create_runnable(timer_elapsed_runnable_name, reentrancy_level=ar_enum.ReentrancyLevel.NON_REENTRANT) + behavior.create_init_event(init_runnable_name) + behavior.create_operation_invoked_event(get_time_runnable_name, "FreeRunningTimer/GetTime") + behavior.create_operation_invoked_event(timer_elapsed_runnable_name, "FreeRunningTimer/IsTimerElapsed") return swc def create_composition_component(package: ar_element.Package, workspace: ar_workspace.Workspace, deps: dict[str, ar_element.ARElement] | None, - **_1) -> ar_element.ApplicationSoftwareComponentType: + **_0) -> ar_element.ApplicationSoftwareComponentType: """ Creates a composition component The created swc must be manually added to the package, otherwise the @@ -77,6 +105,7 @@ def create_composition_component(package: ar_element.Package, assert isinstance(receiver_component, ar_element.ApplicationSoftwareComponentType) assert isinstance(timer_component, ar_element.ApplicationSoftwareComponentType) swc = ar_element.CompositionSwComponentType("CompositionComponent") + package.append(swc) swc.create_require_port("EngineSpeed", engine_speed_interface, com_spec={"init_value": engine_speed_init.ref(), "uses_end_to_end_protection": False}) swc.create_require_port("VehicleSpeed", vehicle_speed_interface, com_spec={"init_value": vehicle_speed_init.ref(), @@ -84,8 +113,6 @@ def create_composition_component(package: ar_element.Package, swc.create_component_prototype(receiver_component) swc.create_component_prototype(timer_component) - # Element must be added to workspace before connectors can be created - package.append(swc) swc.create_connector("TimerComponent/FreeRunningTimer", "ReceiverComponent/FreeRunningTimer", workspace) swc.create_connector("VehicleSpeed", "ReceiverComponent/VehicleSpeed", workspace) swc.create_connector("EngineSpeed", "ReceiverComponent/EngineSpeed", workspace) @@ -95,7 +122,8 @@ def create_composition_component(package: ar_element.Package, ReceiverComponent = factory.GenericComponentTypeTemplate("ReceiverComponent", NAMESPACE, create_ReceiverComponent, - depends=[portinterface.EngineSpeed_I, + depends=[portinterface.EcuM_CurrentMode_I, + portinterface.EngineSpeed_I, portinterface.VehicleSpeed_I, portinterface.FreeRunningTimer_I, constants.EngineSpeed_IV, @@ -118,5 +146,4 @@ def create_composition_component(package: ar_element.Package, constants.EngineSpeed_IV, constants.VehicleSpeed_IV, ReceiverComponent_Implementation, - TimerComponent_Implementation], - append_to_package=False) + TimerComponent_Implementation]) diff --git a/examples/template/demo_system/factory.py b/examples/template/demo_system/factory.py index e76d5aa..ffab03f 100644 --- a/examples/template/demo_system/factory.py +++ b/examples/template/demo_system/factory.py @@ -362,7 +362,7 @@ def __init__(self, namespace_name: str, create_func: CreateFuncType, depends: list[TemplateBase] | None = None, - append_to_package: bool = True) -> None: + append_to_package: bool = False) -> None: super().__init__(element_name, namespace_name, ar_enum.PackageRole.COMPONENT_TYPE, depends, append_to_package) self.create_func = create_func diff --git a/examples/template/demo_system/portinterface.py b/examples/template/demo_system/portinterface.py index 5107c65..8d9dc62 100644 --- a/examples/template/demo_system/portinterface.py +++ b/examples/template/demo_system/portinterface.py @@ -44,7 +44,7 @@ def create_free_running_timer_interface(_0: str, operation.create_out_argument("result", type_ref=boolean_impl_type.ref()) return port_interface -EcuM_CurrentMode = factory.ModeSwitchInterfaceTemplate("EcuM_CurrentMode", NAMESPACE, mode.EcuM_Mode, "currentMode", is_service=True) +EcuM_CurrentMode_I = factory.ModeSwitchInterfaceTemplate("EcuM_CurrentMode_I", NAMESPACE, mode.EcuM_Mode, "currentMode", is_service=True) NvMService_I = factory.GenericPortInterfaceTemplate("NvMService_I", NAMESPACE, create_NvMService_interface) FreeRunningTimer_I = factory.GenericPortInterfaceTemplate("FreeRunningTimer_I", NAMESPACE, diff --git a/examples/template/generate_xml_without_config.py b/examples/template/generate_xml_without_config.py index 84f3ac8..8401f5e 100644 --- a/examples/template/generate_xml_without_config.py +++ b/examples/template/generate_xml_without_config.py @@ -32,6 +32,21 @@ def create_namespaces(workspace: ar_workspace.Workspace): base_ref="/") +def create_behavior_settings(workspace: ar_workspace.Workspace): + """ + Define default event name prefixess + """ + workspace.behavior_settings.update({ + "background_event_prefix": "BT_", + "data_receive_error_event_prefix": "DRET_", + "data_receive_event_prefix": "DRT_", + "init_event_prefix": "IT_", + "operation_invoked_event_prefix": "OIT_", + "swc_mode_manager_error_event_prefix": "MMET_", + "swc_mode_switch_event_prefix": "MST_", + "timing_event_prefix": "TMT_"}) + + def create_documents(workspace: ar_workspace.Workspace) -> None: """ Creates documents @@ -67,6 +82,7 @@ def main(): """Main""" workspace = ar_workspace.Workspace(document_root="generated") create_namespaces(workspace) + create_behavior_settings(workspace) create_documents(workspace) apply_platform_types(workspace) apply_component_types(workspace) diff --git a/examples/template/generated/PortInterfaces.arxml b/examples/template/generated/PortInterfaces.arxml index de8d0a3..ec96e2b 100644 --- a/examples/template/generated/PortInterfaces.arxml +++ b/examples/template/generated/PortInterfaces.arxml @@ -1,6 +1,35 @@ + + ModeDclrGroups + + + EcuM_Mode + /ModeDclrGroups/EcuM_Mode/STARTUP + + + STARTUP + + + RUN + + + POST_RUN + + + SLEEP + + + WAKEUP + + + SHUTDOWN + + + + + PortInterfaces @@ -22,6 +51,14 @@ + + EcuM_CurrentMode_I + true + + currentMode + /ModeDclrGroups/EcuM_Mode + + FreeRunningTimer_I diff --git a/examples/template/generated/ReceiverComponent.arxml b/examples/template/generated/ReceiverComponent.arxml index 3ee7794..af8925a 100644 --- a/examples/template/generated/ReceiverComponent.arxml +++ b/examples/template/generated/ReceiverComponent.arxml @@ -7,6 +7,17 @@ ReceiverComponent + + EcuM_CurrentMode + + + false + /PortInterfaces/EcuM_CurrentMode_I/currentMode + false + + + /PortInterfaces/EcuM_CurrentMode_I + EngineSpeed @@ -51,6 +62,33 @@ ReceiverComponent_InternalBehavior + + + MST_ReceiverComponent_Init + /ComponentTypes/ReceiverComponent/ReceiverComponent_InternalBehavior/ReceiverComponent_Init + ON-ENTRY + + + /ComponentTypes/ReceiverComponent/EcuM_CurrentMode + /PortInterfaces/EcuM_CurrentMode_I/currentMode + /ModeDclrGroups/EcuM_Mode/RUN + + + + + TMT_ReceiverComponent_Run + /ComponentTypes/ReceiverComponent/ReceiverComponent_InternalBehavior/ReceiverComponent_Run + 0.02 + + + + + ReceiverComponent_Init + + + ReceiverComponent_Run + + diff --git a/examples/template/generated/TimerComponent.arxml b/examples/template/generated/TimerComponent.arxml index e6599fb..fe7ee6a 100644 --- a/examples/template/generated/TimerComponent.arxml +++ b/examples/template/generated/TimerComponent.arxml @@ -25,6 +25,41 @@ TimerComponent_InternalBehavior + + + IT_TimerComponent_Init + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_Init + + + OIT_TimerComponent_GetTime_FreeRunningTimer_GetTime + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_GetTime + + /ComponentTypes/TimerComponent/FreeRunningTimer + /PortInterfaces/FreeRunningTimer_I/GetTime + + + + OIT_TimerComponent_IsTimerElapsed_FreeRunningTimer_IsTimerElapsed + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_IsTimerElapsed + + /ComponentTypes/TimerComponent/FreeRunningTimer + /PortInterfaces/FreeRunningTimer_I/IsTimerElapsed + + + + + + TimerComponent_Init + + + TimerComponent_GetTime + NON-REENTRANT + + + TimerComponent_IsTimerElapsed + NON-REENTRANT + + diff --git a/examples/xml/component/application_component.py b/examples/xml/component/application_component.py index bd1336f..9248e39 100644 --- a/examples/xml/component/application_component.py +++ b/examples/xml/component/application_component.py @@ -4,6 +4,35 @@ import os import autosar import autosar.xml.element as ar_element +import autosar.xml.workspace as ar_workspace + + +def create_package_map(workspace: ar_workspace.Workspace): + """ + Creates package map in workspace + """ + workspace.create_package_map({"PlatformBaseTypes": "AUTOSAR_Platform/BaseTypes", + "PlatformImplementationDataTypes": "AUTOSAR_Platform/ImplementationDataTypes", + "PlatformDataConstraints": "AUTOSAR_Platform/DataConstraints", + "PlatformCompuMethods": "AUTOSAR_Platform/CompuMethods", + "Constants": "Constants", + "PortInterfaces": "PortInterfaces", + "ComponentTypes": "ComponentTypes"}) + + +def create_behavior_settings(workspace: ar_workspace.Workspace): + """ + Define default event name prefixess + """ + workspace.behavior_settings.update({ + "background_event_prefix": "BT_", + "data_receive_error_event_prefix": "DRET_", + "data_receive_event_prefix": "DRT_", + "init_event_prefix": "IT_", + "operation_invoked_event_prefix": "OIT_", + "swc_mode_manager_error_event_prefix": "MMET_", + "swc_mode_switch_event_prefix": "MST_", + "timing_event_prefix": "TMT_"}) def create_platform_types(workspace: autosar.xml.Workspace): @@ -97,6 +126,7 @@ def create_application_component(workspace: autosar.xml.Workspace): vehicle_speed_interface = workspace.find_element("PortInterfaces", "VehicleSpeed_I") vehicle_speed_init = workspace.find_element("Constants", "VehicleSpeed_IV") swc = ar_element.ApplicationSoftwareComponentType("SenderComponent") + workspace.add_element("ComponentTypes", swc) swc.create_provide_port("EngineSpeed", engine_speed_interface, com_spec={"init_value": engine_speed_init.ref(), "uses_end_to_end_protection": False, }) @@ -104,7 +134,15 @@ def create_application_component(workspace: autosar.xml.Workspace): "uses_end_to_end_protection": False, }) swc.create_internal_behavior() - workspace.add_element("ComponentTypes", swc) + + init_runnable_name = swc.name + '_Init' + periodic_runnable_name = swc.name + '_Run' + behavior = swc.create_internal_behavior() + behavior.create_runnable(init_runnable_name) + behavior.create_runnable(periodic_runnable_name) + behavior.create_init_event(init_runnable_name) + behavior.create_timing_event(periodic_runnable_name, 0.1) + impl = ar_element.SwcImplementation("SenderComponent_Implementation", behavior_ref=swc.internal_behavior.ref()) workspace.add_element("ComponentTypes", impl) @@ -128,13 +166,8 @@ def main(): Main """ workspace = autosar.xml.Workspace() - workspace.create_package_map({"PlatformBaseTypes": "AUTOSAR_Platform/BaseTypes", - "PlatformImplementationDataTypes": "AUTOSAR_Platform/ImplementationDataTypes", - "PlatformDataConstraints": "AUTOSAR_Platform/DataConstraints", - "PlatformCompuMethods": "AUTOSAR_Platform/CompuMethods", - "Constants": "Constants", - "PortInterfaces": "PortInterfaces", - "ComponentTypes": "ComponentTypes"}) + create_package_map(workspace) + create_behavior_settings(workspace) create_platform_types(workspace) create_sender_receiver_port_interfaces(workspace) create_client_server_interfaces(workspace) diff --git a/examples/xml/component/composition_component.py b/examples/xml/component/composition_component.py index 475c397..d93638c 100644 --- a/examples/xml/component/composition_component.py +++ b/examples/xml/component/composition_component.py @@ -4,6 +4,35 @@ import os import autosar import autosar.xml.element as ar_element +import autosar.xml.workspace as ar_workspace + + +def create_package_map(workspace: ar_workspace.Workspace): + """ + Creates package map in workspace + """ + workspace.create_package_map({"PlatformBaseTypes": "AUTOSAR_Platform/BaseTypes", + "PlatformImplementationDataTypes": "AUTOSAR_Platform/ImplementationDataTypes", + "PlatformDataConstraints": "AUTOSAR_Platform/DataConstraints", + "PlatformCompuMethods": "AUTOSAR_Platform/CompuMethods", + "Constants": "Constants", + "PortInterfaces": "PortInterfaces", + "ComponentTypes": "ComponentTypes"}) + + +def create_behavior_settings(workspace: ar_workspace.Workspace): + """ + Define default event name prefixess + """ + workspace.behavior_settings.update({ + "background_event_prefix": "BT_", + "data_receive_error_event_prefix": "DRET_", + "data_receive_event_prefix": "DRT_", + "init_event_prefix": "IT_", + "operation_invoked_event_prefix": "OIT_", + "swc_mode_manager_error_event_prefix": "MMET_", + "swc_mode_switch_event_prefix": "MST_", + "timing_event_prefix": "TMT_"}) def create_platform_types(workspace: autosar.xml.Workspace): @@ -98,6 +127,7 @@ def create_receiver_component(workspace: autosar.xml.Workspace): vehicle_speed_interface = workspace.find_element("PortInterfaces", "VehicleSpeed_I") vehicle_speed_init = workspace.find_element("Constants", "VehicleSpeed_IV") swc = ar_element.ApplicationSoftwareComponentType("ReceiverComponent") + workspace.add_element("ComponentTypes", swc) swc.create_require_port("EngineSpeed", engine_speed_interface, com_spec={"init_value": engine_speed_init.ref(), "alive_timeout": 0, "enable_update": False, @@ -112,8 +142,14 @@ def create_receiver_component(workspace: autosar.xml.Workspace): }) swc.create_require_port("FreeRunningTimer", timer_interface, com_spec={"GetTime": {}, "IsTimerElapsed": {}}) swc.create_internal_behavior() - workspace.add_element("ComponentTypes", swc) - impl = ar_element.SwcImplementation("ReceiverComponent_Implementation", behavior_ref=swc.internal_behavior.ref()) + init_runnable_name = swc.name + '_Init' + periodic_runnable_name = swc.name + '_Run' + behavior = swc.create_internal_behavior() + behavior.create_runnable(init_runnable_name) + behavior.create_runnable(periodic_runnable_name) + behavior.create_init_event(init_runnable_name) + behavior.create_timing_event(periodic_runnable_name, 0.1) + impl = ar_element.SwcImplementation("ReceiverComponent_Implementation", behavior_ref=behavior.ref()) workspace.add_element("ComponentTypes", impl) @@ -123,12 +159,22 @@ def create_server_component(workspace: autosar.xml.Workspace): """ timer_interface = workspace.find_element("PortInterfaces", "FreeRunningTimer_I") swc = ar_element.ApplicationSoftwareComponentType("TimerComponent") + workspace.add_element("ComponentTypes", swc) swc.create_provide_port("FreeRunningTimer", timer_interface, com_spec={"GetTime": {"queue_length": 1}, "IsTimerElapsed": {"queue_length": 1} }) - swc.create_internal_behavior() - workspace.add_element("ComponentTypes", swc) - impl = ar_element.SwcImplementation("TimerComponent_Implementation", behavior_ref=swc.internal_behavior.ref()) + behavior = swc.create_internal_behavior() + init_runnable_name = swc.name + '_Init' + get_time_runnable_name = "TimerComponent_FreeRunningTimer_GetTime" + is_timer_elapsed_runnable_name = "TimerComponent_FreeRunningTimer_IsTimerElapsed" + behavior = swc.create_internal_behavior() + behavior.create_runnable(init_runnable_name) + behavior.create_runnable(get_time_runnable_name) + behavior.create_runnable(is_timer_elapsed_runnable_name) + behavior.create_init_event(init_runnable_name) + behavior.create_operation_invoked_event(get_time_runnable_name, "FreeRunningTimer/GetTime") + behavior.create_operation_invoked_event(is_timer_elapsed_runnable_name, "FreeRunningTimer/IsTimerElapsed") + impl = ar_element.SwcImplementation("TimerComponent_Implementation", behavior_ref=behavior.ref()) workspace.add_element("ComponentTypes", impl) @@ -173,13 +219,8 @@ def main(): Main """ workspace = autosar.xml.Workspace() - workspace.create_package_map({"PlatformBaseTypes": "AUTOSAR_Platform/BaseTypes", - "PlatformImplementationDataTypes": "AUTOSAR_Platform/ImplementationDataTypes", - "PlatformDataConstraints": "AUTOSAR_Platform/DataConstraints", - "PlatformCompuMethods": "AUTOSAR_Platform/CompuMethods", - "Constants": "Constants", - "PortInterfaces": "PortInterfaces", - "ComponentTypes": "ComponentTypes"}) + create_package_map(workspace) + create_behavior_settings(workspace) create_platform_types(workspace) create_sender_receiver_port_interfaces(workspace) create_client_server_interfaces(workspace) diff --git a/examples/xml/component/data/ReceiverComponent.arxml b/examples/xml/component/data/ReceiverComponent.arxml index 4be205b..607735b 100644 --- a/examples/xml/component/data/ReceiverComponent.arxml +++ b/examples/xml/component/data/ReceiverComponent.arxml @@ -59,6 +59,25 @@ ReceiverComponent_InternalBehavior + + + IT_ReceiverComponent_Init + /ComponentTypes/ReceiverComponent/ReceiverComponent_InternalBehavior/ReceiverComponent_Init + + + TMT_ReceiverComponent_Run + /ComponentTypes/ReceiverComponent/ReceiverComponent_InternalBehavior/ReceiverComponent_Run + 0.1 + + + + + ReceiverComponent_Init + + + ReceiverComponent_Run + + diff --git a/examples/xml/component/data/SenderComponent.arxml b/examples/xml/component/data/SenderComponent.arxml index 1de0398..d11e6c2 100644 --- a/examples/xml/component/data/SenderComponent.arxml +++ b/examples/xml/component/data/SenderComponent.arxml @@ -41,6 +41,25 @@ SenderComponent_InternalBehavior + + + IT_SenderComponent_Init + /ComponentTypes/SenderComponent/SenderComponent_InternalBehavior/SenderComponent_Init + + + TMT_SenderComponent_Run + /ComponentTypes/SenderComponent/SenderComponent_InternalBehavior/SenderComponent_Run + 0.1 + + + + + SenderComponent_Init + + + SenderComponent_Run + + diff --git a/examples/xml/component/data/TimerComponent.arxml b/examples/xml/component/data/TimerComponent.arxml index e6599fb..0b4dfaa 100644 --- a/examples/xml/component/data/TimerComponent.arxml +++ b/examples/xml/component/data/TimerComponent.arxml @@ -25,6 +25,39 @@ TimerComponent_InternalBehavior + + + IT_TimerComponent_Init + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_Init + + + OIT_TimerComponent_FreeRunningTimer_GetTime_FreeRunningTimer_GetTime + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_FreeRunningTimer_GetTime + + /ComponentTypes/TimerComponent/FreeRunningTimer + /PortInterfaces/FreeRunningTimer_I/GetTime + + + + OIT_TimerComponent_FreeRunningTimer_IsTimerElapsed_FreeRunningTimer_IsTimerElapsed + /ComponentTypes/TimerComponent/TimerComponent_InternalBehavior/TimerComponent_FreeRunningTimer_IsTimerElapsed + + /ComponentTypes/TimerComponent/FreeRunningTimer + /PortInterfaces/FreeRunningTimer_I/IsTimerElapsed + + + + + + TimerComponent_Init + + + TimerComponent_FreeRunningTimer_GetTime + + + TimerComponent_FreeRunningTimer_IsTimerElapsed + + diff --git a/examples/xml/port_interface/data/mode_declarations.arxml b/examples/xml/port_interface/data/mode_declarations.arxml index 4bfd39e..def741d 100644 --- a/examples/xml/port_interface/data/mode_declarations.arxml +++ b/examples/xml/port_interface/data/mode_declarations.arxml @@ -12,14 +12,17 @@ OFF - ACCESSORY + PARKING - RUNNING + ACCESSORY CRANKING + + RUNNING + diff --git a/examples/xml/port_interface/mode_switch_interface.py b/examples/xml/port_interface/mode_switch_interface.py index 254abc7..dc0acf5 100644 --- a/examples/xml/port_interface/mode_switch_interface.py +++ b/examples/xml/port_interface/mode_switch_interface.py @@ -11,9 +11,10 @@ def create_mode_declaration_groups(workspace: autosar.xml.Workspace): Creates mode declarations """ vehicle_mode = ar_element.ModeDeclarationGroup("VehicleMode", ["OFF", + "PARKING", "ACCESSORY", - "RUNNING", - "CRANKING"]) + "CRANKING", + "RUNNING"]) workspace.add_element("ModeDeclarations", vehicle_mode) vehicle_mode.initial_mode_ref = vehicle_mode.find("OFF").ref() diff --git a/src/autosar/base.py b/src/autosar/base.py index 6115ab5..5471a6c 100644 --- a/src/autosar/base.py +++ b/src/autosar/base.py @@ -18,6 +18,8 @@ def split_ref_strict(ref: str) -> list[str] | None: sep = "/" if not isinstance(ref, str): raise TypeError("ref: Must be a string") + if len(ref) == 0: + raise ValueError("String cannot be empty") if ref[0] == sep: raise ValueError("ref: String cannot start with '/'") return ref.split(sep) diff --git a/src/autosar/xml/element.py b/src/autosar/xml/element.py index efc5ba6..127a9f5 100644 --- a/src/autosar/xml/element.py +++ b/src/autosar/xml/element.py @@ -6421,8 +6421,36 @@ def _make_unique_event_name(self, event_name: str) -> str: Calling this function could potentially invalidate existing event references. Note: Not yet implemented """ - # TODO: Implement this function - return event_name + return self._make_unique_name_in_list(self.events, event_name) + + def _make_unique_name_in_list(self, elements: list[Referrable], base_name: str): + """ + Attempts to find a unique name in the list of elements. + This function can modify names in the given list. + If an element with the name base_name already exists in the list it will + append "_0" to the existing element and any newly added element will have + its suffix automatically increased by 1. + Returns a new name which is guaranteed to be unique in the given list + """ + has_index = False + highest_index = 0 + unpatched_elem: Referrable | None = None + expr = re.compile(base_name + r'_(\d+)') + for element in elements: + result = expr.match(element.name) + if result is not None: + has_index = True + index = int(result.group(1)) + if index > highest_index: + highest_index = index + elif element.name == base_name: + unpatched_elem = element + if unpatched_elem is not None: + unpatched_elem.name = '_'.join([unpatched_elem.name, '0']) + if has_index or unpatched_elem is not None: + return '_'.join([base_name, str(highest_index + 1)]) + else: + return base_name def create_background_event(self, runnable_name: str, @@ -6719,7 +6747,10 @@ def create_swc_mode_mode_switch_event(self, raise RuntimeError(msg) assert isinstance(event_name, str) unique_event_name = self._make_unique_event_name(event_name) + expected_formats = "Expected formats: '', '/', tuple[str, str]" if isinstance(mode_ref, str): + if len(mode_ref) == 0: + raise ValueError("mode_ref: Invalid argument. " + expected_formats) context_port, context_mode_declaration_group, target_mode_declaration = ( self._get_swc_mode_switch_event_args(workspace, swc, mode_ref)) event = SwcModeSwitchEvent.make(unique_event_name, @@ -6734,11 +6765,16 @@ def create_swc_mode_mode_switch_event(self, raise ValueError("mode_ref: Must be exactly two elements in tuple or list") instance_refs = [] for ref in mode_ref: - context_port, context_mode_declaration_group, target_mode_declaration = ( - self._get_swc_mode_switch_event_args(workspace, swc, ref)) - instance_refs.append(RModeInAtomicSwcInstanceRef(context_port.ref(), - context_mode_declaration_group.ref(), - target_mode_declaration.ref())) + if isinstance(ref, str): + if len(ref) == 0: + raise ValueError("mode_ref: Invalid argument. " + expected_formats) + context_port, context_mode_declaration_group, target_mode_declaration = ( + self._get_swc_mode_switch_event_args(workspace, swc, ref)) + instance_refs.append(RModeInAtomicSwcInstanceRef(context_port.ref(), + context_mode_declaration_group.ref(), + target_mode_declaration.ref())) + else: + raise TypeError(f"mode_ref: Invalid type '{str(type(ref))}'. " + expected_formats) event = SwcModeSwitchEvent(unique_event_name, runnable.ref(), activation, @@ -6788,15 +6824,14 @@ def _get_swc_mode_switch_event_args(self, """ name_parts = split_ref_strict(mode_ref) if len(name_parts) != 2: - raise ValueError("port_mode: Formatting error, expected /") - else: - port_name, mode_declaration_name = name_parts[0], name_parts[1] + raise ValueError("mode_ref: Formatting error, expected /") + port_name, mode_declaration_name = name_parts[0], name_parts[1] context_port = swc.find_r_port(port_name) if context_port is None: - raise ValueError(f"port_mode: '{mode_ref}' does not name an existing R-PORT or PR-PORT") + raise ValueError(f"mode_ref: '{mode_ref}' does not name an existing R-PORT or PR-PORT") context_mode_declaration_group = swc.get_mode_declaration_group_in_port(context_port) if context_mode_declaration_group is None: - msg = f"port_mode: '{mode_ref}' does not name a valid ModeDeclarationGroupPrototype in port interface" + msg = f"mode_ref: '{mode_ref}' does not name a valid ModeDeclarationGroupPrototype in port interface" raise ValueError(msg) target_mode_declaration_group: ModeDeclarationGroup | None target_mode_declaration_group = workspace.find(context_mode_declaration_group.type_ref) @@ -6804,5 +6839,5 @@ def _get_swc_mode_switch_event_args(self, raise ar_except.InvalidReferenceError(str(context_mode_declaration_group.type_ref)) target_mode_declaration: ModeDeclaration | None = target_mode_declaration_group.find(mode_declaration_name) if target_mode_declaration is None: - raise ValueError(f"port_mode: '{mode_ref}' does not name a valid mode declaration in ModeDeclarationGroup") + raise ValueError(f"mode_ref: '{mode_ref}' does not name a valid mode declaration in ModeDeclarationGroup") return context_port, context_mode_declaration_group, target_mode_declaration diff --git a/tests/xml/test_software_component_builder.py b/tests/xml/test_software_component_builder.py index 5e1ecb2..5737914 100644 --- a/tests/xml/test_software_component_builder.py +++ b/tests/xml/test_software_component_builder.py @@ -536,6 +536,32 @@ def test_create_swc_mode_switch_event_with_transition(self): "/PortInterfaces/VehicleMode_I/mode") self.assertEqual(str(event.mode[1].target_mode_declaration), "/ModeDeclarations/VehicleMode/ACCESSORY") + def test_create_multiple_swc_mode_switch_events_with_same_base_name(self): + workspace = autosar.xml.Workspace() + workspace.behavior_settings.set_value("swc_mode_switch_event_prefix", "MST_") + swc = self.create_swc(workspace) + behavior = swc.internal_behavior + behavior.create_runnable("MyApplication_Init") + event1 = behavior.create_swc_mode_mode_switch_event("MyApplication_Init", + "VehicleMode/ACCESSORY", + ar_enum.ModeActivationKind.ON_ENTRY) + event2 = behavior.create_swc_mode_mode_switch_event("MyApplication_Init", + "VehicleMode/PARKING", + ar_enum.ModeActivationKind.ON_ENTRY) + event3 = behavior.create_swc_mode_mode_switch_event("MyApplication_Init", + "VehicleMode/RUNNING", + ar_enum.ModeActivationKind.ON_ENTRY) + + self.assertIsInstance(event1, ar_element.SwcModeSwitchEvent) + self.assertIsInstance(event2, ar_element.SwcModeSwitchEvent) + self.assertIsInstance(event3, ar_element.SwcModeSwitchEvent) + self.assertEqual(event1.name, "MST_MyApplication_Init_0",) + self.assertEqual(event2.name, "MST_MyApplication_Init_1",) + self.assertEqual(event3.name, "MST_MyApplication_Init_2",) + self.assertEqual(str(event1.mode.target_mode_declaration), "/ModeDeclarations/VehicleMode/ACCESSORY") + self.assertEqual(str(event2.mode.target_mode_declaration), "/ModeDeclarations/VehicleMode/PARKING") + self.assertEqual(str(event3.mode.target_mode_declaration), "/ModeDeclarations/VehicleMode/RUNNING") + def test_create_timing_event_without_offset(self): workspace = autosar.xml.Workspace() workspace.behavior_settings.set_value("timing_event_prefix", "TMT_")