py_canoe 3.0.4__py3-none-any.whl → 26.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py_canoe/__init__.py +2 -1
- py_canoe/canoe.py +911 -0
- py_canoe/core/__init__.py +0 -0
- py_canoe/core/application.py +170 -0
- py_canoe/core/bus.py +301 -0
- py_canoe/core/capl.py +59 -0
- py_canoe/core/child_elements/__init__.py +0 -0
- py_canoe/core/child_elements/application_model.py +24 -0
- py_canoe/core/child_elements/application_model_file.py +21 -0
- py_canoe/core/child_elements/application_model_files.py +22 -0
- py_canoe/core/child_elements/application_model_setup.py +15 -0
- py_canoe/core/child_elements/application_models.py +22 -0
- py_canoe/core/child_elements/application_socket.py +11 -0
- py_canoe/core/child_elements/application_specific_module.py +24 -0
- py_canoe/core/child_elements/application_specific_modules.py +16 -0
- py_canoe/core/child_elements/audio_interface.py +28 -0
- py_canoe/core/child_elements/available_modules.py +22 -0
- py_canoe/core/child_elements/basic_module.py +19 -0
- py_canoe/core/child_elements/basic_modules.py +16 -0
- py_canoe/core/child_elements/c_libraries.py +28 -0
- py_canoe/core/child_elements/c_library.py +33 -0
- py_canoe/core/child_elements/can_controller.py +74 -0
- py_canoe/core/child_elements/capl_function.py +17 -0
- py_canoe/core/child_elements/ccp_setup.py +15 -0
- py_canoe/core/child_elements/channel.py +20 -0
- py_canoe/core/child_elements/channels.py +19 -0
- py_canoe/core/child_elements/communication_setup.py +23 -0
- py_canoe/core/child_elements/compile_result.py +22 -0
- py_canoe/core/child_elements/configured_channel.py +48 -0
- py_canoe/core/child_elements/configured_channels.py +21 -0
- py_canoe/core/child_elements/configured_module.py +82 -0
- py_canoe/core/child_elements/configured_modules.py +61 -0
- py_canoe/core/child_elements/connected_modules.py +14 -0
- py_canoe/core/child_elements/data_source.py +42 -0
- py_canoe/core/child_elements/data_source_file.py +21 -0
- py_canoe/core/child_elements/data_source_files.py +22 -0
- py_canoe/core/child_elements/data_source_issue.py +22 -0
- py_canoe/core/child_elements/data_source_issues.py +16 -0
- py_canoe/core/child_elements/data_source_setup.py +17 -0
- py_canoe/core/child_elements/data_sources.py +27 -0
- py_canoe/core/child_elements/database_setup.py +62 -0
- py_canoe/core/child_elements/device.py +34 -0
- py_canoe/core/child_elements/devices.py +13 -0
- py_canoe/core/child_elements/diagnostic.py +22 -0
- py_canoe/core/child_elements/diagnostic_request.py +59 -0
- py_canoe/core/child_elements/diagnostic_response.py +34 -0
- py_canoe/core/child_elements/diagnostic_responses.py +13 -0
- py_canoe/core/child_elements/diagnostics_setup.py +254 -0
- py_canoe/core/child_elements/distributed_mode.py +74 -0
- py_canoe/core/child_elements/encoding.py +27 -0
- py_canoe/core/child_elements/encodings.py +13 -0
- py_canoe/core/child_elements/environment_array.py +13 -0
- py_canoe/core/child_elements/environment_group.py +22 -0
- py_canoe/core/child_elements/environment_info.py +14 -0
- py_canoe/core/child_elements/environment_variable.py +55 -0
- py_canoe/core/child_elements/fdx_files.py +50 -0
- py_canoe/core/child_elements/file_group_data_source.py +17 -0
- py_canoe/core/child_elements/general_setup.py +66 -0
- py_canoe/core/child_elements/macros_setup.py +52 -0
- py_canoe/core/child_elements/mc_ecus.py +428 -0
- py_canoe/core/child_elements/measurement_setup.py +269 -0
- py_canoe/core/child_elements/modules.py +87 -0
- py_canoe/core/child_elements/most_disassembler.py +21 -0
- py_canoe/core/child_elements/most_network_interface.py +4 -0
- py_canoe/core/child_elements/namespace.py +21 -0
- py_canoe/core/child_elements/namespaces.py +19 -0
- py_canoe/core/child_elements/network.py +18 -0
- py_canoe/core/child_elements/network_adapters.py +13 -0
- py_canoe/core/child_elements/nodes.py +119 -0
- py_canoe/core/child_elements/open_configuration_result.py +0 -0
- py_canoe/core/child_elements/panel_setup.py +97 -0
- py_canoe/core/child_elements/participant.py +17 -0
- py_canoe/core/child_elements/participants.py +22 -0
- py_canoe/core/child_elements/ports.py +81 -0
- py_canoe/core/child_elements/replay_collection.py +56 -0
- py_canoe/core/child_elements/security_configuration.py +20 -0
- py_canoe/core/child_elements/security_setup.py +31 -0
- py_canoe/core/child_elements/signals.py +39 -0
- py_canoe/core/child_elements/simulation_setup.py +0 -0
- py_canoe/core/child_elements/single_file_data_source.py +13 -0
- py_canoe/core/child_elements/snippet_setup.py +68 -0
- py_canoe/core/child_elements/standalone_mode.py +0 -0
- py_canoe/core/child_elements/start_value_list.py +0 -0
- py_canoe/core/child_elements/symbol_mappings.py +0 -0
- py_canoe/core/child_elements/tcp_ip_stack_setting.py +0 -0
- py_canoe/core/child_elements/test_configurations.py +0 -0
- py_canoe/core/child_elements/test_environment.py +64 -0
- py_canoe/core/child_elements/test_environments.py +26 -0
- py_canoe/core/child_elements/test_module.py +213 -0
- py_canoe/core/child_elements/test_modules.py +23 -0
- py_canoe/core/child_elements/test_setup.py +16 -0
- py_canoe/core/child_elements/test_setup_folder_ext.py +36 -0
- py_canoe/core/child_elements/test_setup_folders.py +25 -0
- py_canoe/core/child_elements/user_files.py +0 -0
- py_canoe/core/child_elements/variable.py +144 -0
- py_canoe/core/child_elements/variable_events.py +14 -0
- py_canoe/core/child_elements/variables.py +29 -0
- py_canoe/core/child_elements/variables_file.py +15 -0
- py_canoe/core/child_elements/variables_files.py +19 -0
- py_canoe/core/child_elements/visual_sequence_setup.py +46 -0
- py_canoe/core/child_elements/vt_system.py +83 -0
- py_canoe/core/child_elements/vtt_sut_import_result.py +21 -0
- py_canoe/core/child_elements/write.py +71 -0
- py_canoe/core/child_elements/xcp_setup.py +12 -0
- py_canoe/core/configuration.py +509 -0
- py_canoe/core/environment.py +59 -0
- py_canoe/core/measurement.py +149 -0
- py_canoe/core/networks.py +103 -0
- py_canoe/core/performance.py +21 -0
- py_canoe/core/simulation.py +53 -0
- py_canoe/core/system.py +164 -0
- py_canoe/core/ui.py +53 -0
- py_canoe/core/version.py +54 -0
- py_canoe/helpers/__init__.py +0 -0
- py_canoe/helpers/common.py +78 -0
- {py_canoe-3.0.4.dist-info → py_canoe-26.0.2.dist-info}/METADATA +332 -322
- py_canoe-26.0.2.dist-info/RECORD +118 -0
- {py_canoe-3.0.4.dist-info → py_canoe-26.0.2.dist-info}/WHEEL +1 -1
- py_canoe/py_canoe.py +0 -2586
- py_canoe/py_canoe_utils/logging_collection.py +0 -345
- py_canoe/py_canoe_utils/py_canoe_logger.py +0 -29
- py_canoe-3.0.4.dist-info/LICENSE +0 -21
- py_canoe-3.0.4.dist-info/RECORD +0 -8
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Iterable, Union
|
|
2
|
+
if TYPE_CHECKING:
|
|
3
|
+
from py_canoe.core.application import Application
|
|
4
|
+
from py_canoe.core.child_elements.measurement_setup import Logging, ExporterSymbol, Message
|
|
5
|
+
import os
|
|
6
|
+
import win32com.client
|
|
7
|
+
|
|
8
|
+
from py_canoe.core.child_elements.c_libraries import CLibraries
|
|
9
|
+
from py_canoe.core.child_elements.communication_setup import CommunicationSetup
|
|
10
|
+
from py_canoe.core.child_elements.distributed_mode import DistributedMode
|
|
11
|
+
from py_canoe.core.child_elements.fdx_files import FDXFiles
|
|
12
|
+
from py_canoe.core.child_elements.general_setup import GeneralSetup
|
|
13
|
+
from py_canoe.core.child_elements.measurement_setup import MeasurementSetup
|
|
14
|
+
from py_canoe.core.child_elements.database_setup import Databases
|
|
15
|
+
from py_canoe.core.child_elements.replay_collection import ReplayCollection
|
|
16
|
+
from py_canoe.core.child_elements.test_setup import TestSetup
|
|
17
|
+
from py_canoe.helpers.common import logger, wait
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConfigurationEvents:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.CONFIGURATION_CLOSED = False
|
|
23
|
+
self.SYSTEM_VARIABLES_DEFINITION_CHANGED = False
|
|
24
|
+
|
|
25
|
+
def OnClose(self):
|
|
26
|
+
self.CONFIGURATION_CLOSED = True
|
|
27
|
+
|
|
28
|
+
def OnSystemVariablesDefinitionChanged(self):
|
|
29
|
+
self.SYSTEM_VARIABLES_DEFINITION_CHANGED = True
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Configuration:
|
|
33
|
+
"""
|
|
34
|
+
The Configuration object represents the active configuration.
|
|
35
|
+
"""
|
|
36
|
+
def __init__(self, app: 'Application'):
|
|
37
|
+
self.app = app
|
|
38
|
+
self.bus_types = self.app.bus_types
|
|
39
|
+
self.com_object = win32com.client.Dispatch(self.app.com_object.Configuration)
|
|
40
|
+
# self.configuration_events: ConfigurationEvents = win32com.client.WithEvents(self.com_object, ConfigurationEvents)
|
|
41
|
+
self.configuration_test_setup = lambda: self.test_setup
|
|
42
|
+
self.__test_setup_environments = self.configuration_test_setup().test_environments.fetch_all_test_environments()
|
|
43
|
+
self.__test_modules = list()
|
|
44
|
+
|
|
45
|
+
def fetch_test_modules(self):
|
|
46
|
+
for te_name, te_inst in self.__test_setup_environments.items():
|
|
47
|
+
for tm_name, tm_inst in te_inst.get_all_test_modules().items():
|
|
48
|
+
self.__test_modules.append({'name': tm_name, 'object': tm_inst, 'environment': te_name})
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def c_libraries(self) -> 'CLibraries':
|
|
52
|
+
return CLibraries(self.com_object.CLibraries)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def comment(self) -> str:
|
|
56
|
+
return self.com_object.Comment
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def communication_setup(self) -> 'CommunicationSetup':
|
|
60
|
+
return CommunicationSetup(self.com_object.CommunicationSetup)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def distributed_mode(self) -> 'DistributedMode':
|
|
64
|
+
return DistributedMode(self.com_object.DistributedMode)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def fdx_enabled(self) -> bool:
|
|
68
|
+
return self.com_object.FDXEnabled
|
|
69
|
+
|
|
70
|
+
@fdx_enabled.setter
|
|
71
|
+
def fdx_enabled(self, enabled: bool):
|
|
72
|
+
self.com_object.FDXEnabled = enabled
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def fdx_files(self) -> 'FDXFiles':
|
|
76
|
+
return FDXFiles(self.com_object.FDXFiles)
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def full_name(self) -> str:
|
|
80
|
+
return self.com_object.FullName
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def general_setup(self) -> 'GeneralSetup':
|
|
84
|
+
return GeneralSetup(self.com_object.GeneralSetup)
|
|
85
|
+
|
|
86
|
+
# GlobalTcpIpStackSetting
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def mode(self) -> int:
|
|
90
|
+
return self.com_object.Mode
|
|
91
|
+
|
|
92
|
+
@mode.setter
|
|
93
|
+
def mode(self, type: int):
|
|
94
|
+
self.com_object.Mode = type
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def modified(self) -> bool:
|
|
98
|
+
return self.com_object.Modified
|
|
99
|
+
|
|
100
|
+
@modified.setter
|
|
101
|
+
def modified(self, modified: bool):
|
|
102
|
+
self.com_object.Modified = modified
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def name(self) -> str:
|
|
106
|
+
return self.com_object.Name
|
|
107
|
+
|
|
108
|
+
# NETTargetFramework
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def offline_setup(self) -> 'MeasurementSetup':
|
|
112
|
+
return MeasurementSetup(self.com_object.OfflineSetup)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def online_setup(self) -> 'MeasurementSetup':
|
|
116
|
+
return MeasurementSetup(self.com_object.OnlineSetup)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def path(self) -> str:
|
|
120
|
+
return self.com_object.Path
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def read_only(self) -> bool:
|
|
124
|
+
return self.com_object.ReadOnly
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def saved(self) -> bool:
|
|
128
|
+
return self.com_object.Saved
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def test_setup(self) -> 'TestSetup':
|
|
132
|
+
return TestSetup(self.com_object.TestSetup)
|
|
133
|
+
|
|
134
|
+
# Sensor
|
|
135
|
+
|
|
136
|
+
# SimulationSetup
|
|
137
|
+
|
|
138
|
+
# StandaloneMode
|
|
139
|
+
|
|
140
|
+
# StartValueList
|
|
141
|
+
|
|
142
|
+
# SymbolMappings
|
|
143
|
+
|
|
144
|
+
# TestConfigurations
|
|
145
|
+
|
|
146
|
+
# TestSetup
|
|
147
|
+
|
|
148
|
+
# UserFiles
|
|
149
|
+
|
|
150
|
+
# VTSystem
|
|
151
|
+
|
|
152
|
+
def compile_and_verify(self) -> bool:
|
|
153
|
+
self.com_object.CompileAndVerify()
|
|
154
|
+
|
|
155
|
+
def save(self) -> bool:
|
|
156
|
+
try:
|
|
157
|
+
if self.saved:
|
|
158
|
+
logger.warning("⚠️ CANoe configuration is already saved.")
|
|
159
|
+
return True
|
|
160
|
+
self.com_object.Save()
|
|
161
|
+
logger.info("📢 CANoe configuration saved 💾 successfully 🎉")
|
|
162
|
+
return True
|
|
163
|
+
except Exception as e:
|
|
164
|
+
logger.error(f"❌ Error saving CANoe configuration: {e}")
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
def save_as(self, path: str, major: int, minor: int, prompt_user: bool = False, create_dir: bool = True) -> bool:
|
|
168
|
+
try:
|
|
169
|
+
if create_dir:
|
|
170
|
+
dir_path = os.path.dirname(path)
|
|
171
|
+
if dir_path:
|
|
172
|
+
os.makedirs(dir_path, exist_ok=True)
|
|
173
|
+
logger.info(f'📂 Created directory {dir_path} for saving configuration')
|
|
174
|
+
self.com_object.SaveAs(path, major, minor, prompt_user)
|
|
175
|
+
logger.info(f"📢 CANoe configuration saved 💾 as {path} successfully 🎉")
|
|
176
|
+
return True
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.error(f"❌ Error saving CANoe configuration as '{path}': {e}")
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
def get_can_bus_statistics(self, channel: int) -> dict:
|
|
182
|
+
try:
|
|
183
|
+
can_stat_obj = self.online_setup.bus_statistics.BusStatistic(self.bus_types['CAN'], channel)
|
|
184
|
+
keys = [
|
|
185
|
+
'BusLoad', 'ChipState', 'Error', 'ErrorTotal', 'Extended', 'ExtendedTotal',
|
|
186
|
+
'ExtendedRemote', 'ExtendedRemoteTotal', 'Overload', 'OverloadTotal', 'PeakLoad',
|
|
187
|
+
'RxErrorCount', 'Standard', 'StandardTotal', 'StandardRemote', 'StandardRemoteTotal',
|
|
188
|
+
'TxErrorCount'
|
|
189
|
+
]
|
|
190
|
+
can_bus_stat_info = {key.lower(): getattr(can_stat_obj, key) for key in keys}
|
|
191
|
+
logger.info(f'📜 CAN bus channel ({channel}) statistics:')
|
|
192
|
+
for key, value in can_bus_stat_info.items():
|
|
193
|
+
logger.info(f" {key}: {value}")
|
|
194
|
+
return can_bus_stat_info
|
|
195
|
+
except Exception as e:
|
|
196
|
+
logger.error(f"❌ Error retrieving CAN bus statistics for channel {channel}: {e}")
|
|
197
|
+
return {}
|
|
198
|
+
|
|
199
|
+
def add_offline_source_log_file(self, absolute_log_file_path: str) -> bool:
|
|
200
|
+
try:
|
|
201
|
+
if not os.path.isfile(absolute_log_file_path):
|
|
202
|
+
logger.error(f"❌ Error: Offline source log file '{absolute_log_file_path}' does not exist.")
|
|
203
|
+
return False
|
|
204
|
+
offline_sources_obj = self.com_object.OfflineSetup.Source.Sources
|
|
205
|
+
offline_sources_files = [offline_sources_obj.Item(i) for i in range(1, offline_sources_obj.Count + 1)]
|
|
206
|
+
file_already_added = any([file == absolute_log_file_path for file in offline_sources_files])
|
|
207
|
+
if file_already_added:
|
|
208
|
+
logger.warning(f"⚠️ Offline source log file '{absolute_log_file_path}' is already added.")
|
|
209
|
+
else:
|
|
210
|
+
offline_sources_obj.Add(absolute_log_file_path)
|
|
211
|
+
logger.info(f'📢 File "{absolute_log_file_path}" added as offline source')
|
|
212
|
+
return True
|
|
213
|
+
except Exception as e:
|
|
214
|
+
logger.error(f"❌ Error adding offline source log file '{absolute_log_file_path}': {e}")
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
def set_replay_block_file(self, block_name: str, recording_file_path: str) -> bool:
|
|
218
|
+
try:
|
|
219
|
+
replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
|
|
220
|
+
replay_blocks_obj_dict = dict()
|
|
221
|
+
for i in range(1, replay_collection_obj.count + 1):
|
|
222
|
+
replay_block_obj = replay_collection_obj.item(i)
|
|
223
|
+
replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
|
|
224
|
+
if block_name in replay_blocks_obj_dict:
|
|
225
|
+
replay_blocks_obj_dict[block_name].path = recording_file_path
|
|
226
|
+
logger.info(f"📢 Replay block path for '{block_name}' set to '{recording_file_path}'")
|
|
227
|
+
return True
|
|
228
|
+
else:
|
|
229
|
+
logger.warning(f"⚠️ Replay block '{block_name}' not found")
|
|
230
|
+
return False
|
|
231
|
+
except Exception as e:
|
|
232
|
+
logger.error(f"❌ Error setting replay block file for '{block_name}': {e}")
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
def control_replay_block(self, block_name: str, start_stop: bool) -> bool:
|
|
236
|
+
try:
|
|
237
|
+
replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
|
|
238
|
+
replay_blocks_obj_dict = dict()
|
|
239
|
+
for i in range(1, replay_collection_obj.count + 1):
|
|
240
|
+
replay_block_obj = replay_collection_obj.item(i)
|
|
241
|
+
replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
|
|
242
|
+
if block_name in replay_blocks_obj_dict:
|
|
243
|
+
if start_stop:
|
|
244
|
+
replay_blocks_obj_dict[block_name].start()
|
|
245
|
+
logger.info(f"📢 Replay block '{block_name}' started")
|
|
246
|
+
else:
|
|
247
|
+
replay_blocks_obj_dict[block_name].stop()
|
|
248
|
+
logger.info(f"📢 Replay block '{block_name}' stopped")
|
|
249
|
+
return True
|
|
250
|
+
else:
|
|
251
|
+
logger.warning(f"⚠️ Replay block '{block_name}' not found")
|
|
252
|
+
return False
|
|
253
|
+
except Exception as e:
|
|
254
|
+
logger.error(f"❌ Error controlling replay block '{block_name}': {e}")
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
def enable_disable_replay_block(self, block_name: str, enable_disable: bool) -> bool:
|
|
258
|
+
try:
|
|
259
|
+
replay_collection_obj = ReplayCollection(self.com_object.SimulationSetup.ReplayCollection)
|
|
260
|
+
replay_blocks_obj_dict = dict()
|
|
261
|
+
for i in range(1, replay_collection_obj.count + 1):
|
|
262
|
+
replay_block_obj = replay_collection_obj.item(i)
|
|
263
|
+
replay_blocks_obj_dict[replay_block_obj.name] = replay_block_obj
|
|
264
|
+
if block_name in replay_blocks_obj_dict:
|
|
265
|
+
replay_blocks_obj_dict[block_name].enabled = enable_disable
|
|
266
|
+
logger.info(f"📢 Replay block '{block_name}' {'enabled' if enable_disable else 'disabled'}")
|
|
267
|
+
return True
|
|
268
|
+
else:
|
|
269
|
+
logger.warning(f"⚠️ Replay block '{block_name}' not found")
|
|
270
|
+
return False
|
|
271
|
+
except Exception as e:
|
|
272
|
+
logger.error(f"❌ Error enabling/disabling replay block '{block_name}': {e}")
|
|
273
|
+
return False
|
|
274
|
+
|
|
275
|
+
def get_test_environments(self) -> dict:
|
|
276
|
+
try:
|
|
277
|
+
return self.__test_setup_environments
|
|
278
|
+
except Exception as e:
|
|
279
|
+
logger.error(f'❌ failed to get test environments. {e}')
|
|
280
|
+
return {}
|
|
281
|
+
|
|
282
|
+
def get_test_modules(self, env_name: str) -> dict:
|
|
283
|
+
try:
|
|
284
|
+
test_environments = self.get_test_environments()
|
|
285
|
+
if len(test_environments) > 0:
|
|
286
|
+
if env_name in test_environments.keys():
|
|
287
|
+
return test_environments[env_name].get_all_test_modules()
|
|
288
|
+
else:
|
|
289
|
+
logger.warning(f'⚠️ "{env_name}" not found in configuration')
|
|
290
|
+
return {}
|
|
291
|
+
else:
|
|
292
|
+
logger.warning('⚠️ Zero test environments found in configuration. Not possible to fetch test modules')
|
|
293
|
+
return {}
|
|
294
|
+
except Exception as e:
|
|
295
|
+
logger.error(f'❌ failed to get test modules. {e}')
|
|
296
|
+
return {}
|
|
297
|
+
|
|
298
|
+
def execute_test_module(self, test_module_name: str) -> int:
|
|
299
|
+
try:
|
|
300
|
+
test_verdict = {0: 'NotAvailable',
|
|
301
|
+
1: 'Passed',
|
|
302
|
+
2: 'Failed',
|
|
303
|
+
3: 'None (not available for test modules)',
|
|
304
|
+
4: 'Inconclusive (not available for test modules)',
|
|
305
|
+
5: 'ErrorInTestSystem (not available for test modules)', }
|
|
306
|
+
execution_result = 0
|
|
307
|
+
test_module_found = False
|
|
308
|
+
test_env_name = ''
|
|
309
|
+
for tm in self.__test_modules:
|
|
310
|
+
if tm['name'] == test_module_name:
|
|
311
|
+
test_module_found = True
|
|
312
|
+
tm_obj = tm['object']
|
|
313
|
+
test_env_name = tm['environment']
|
|
314
|
+
logger.info(f'🔎 test module "{test_module_name}" found in "{test_env_name}"')
|
|
315
|
+
tm_obj.start()
|
|
316
|
+
tm_obj.wait_for_completion()
|
|
317
|
+
execution_result = tm_obj.verdict
|
|
318
|
+
break
|
|
319
|
+
else:
|
|
320
|
+
continue
|
|
321
|
+
if test_module_found and (execution_result == 1):
|
|
322
|
+
logger.info(f'🧪🟢 test module "{test_env_name}.{test_module_name}" verdict = {test_verdict[execution_result]}')
|
|
323
|
+
elif test_module_found and (execution_result != 1):
|
|
324
|
+
logger.info(f'🧪🔴 test module "{test_env_name}.{test_module_name}" verdict = {test_verdict[execution_result]}')
|
|
325
|
+
else:
|
|
326
|
+
logger.warning(f'🧪⚠️ test module "{test_module_name}" not found. not possible to execute')
|
|
327
|
+
return execution_result
|
|
328
|
+
except Exception as e:
|
|
329
|
+
logger.error(f'❌ failed to execute test module. {e}')
|
|
330
|
+
return 0
|
|
331
|
+
|
|
332
|
+
def stop_test_module(self, test_module_name: str):
|
|
333
|
+
try:
|
|
334
|
+
for tm in self.__test_modules:
|
|
335
|
+
if tm['name'] == test_module_name:
|
|
336
|
+
tm['object'].stop()
|
|
337
|
+
test_env_name = tm['environment']
|
|
338
|
+
logger.info(f'🧪⏹️ test module "{test_module_name}" in test environment "{test_env_name}" stopped 🧍♂️')
|
|
339
|
+
else:
|
|
340
|
+
logger.warning(f'🧪⚠️ test module "{test_module_name}" not found. not possible to execute')
|
|
341
|
+
except Exception as e:
|
|
342
|
+
logger.error(f'❌ failed to stop test module. {e}')
|
|
343
|
+
|
|
344
|
+
def execute_all_test_modules_in_test_env(self, env_name: str):
|
|
345
|
+
try:
|
|
346
|
+
test_modules = self.get_test_modules(env_name=env_name)
|
|
347
|
+
if test_modules:
|
|
348
|
+
for tm_name in test_modules.keys():
|
|
349
|
+
self.execute_test_module(tm_name)
|
|
350
|
+
else:
|
|
351
|
+
logger.warning(f'🧪⚠️ test modules not available in "{env_name}" test environment')
|
|
352
|
+
except Exception as e:
|
|
353
|
+
logger.error(f'🧪❌ failed to execute all test modules in "{env_name}" test environment. {e}')
|
|
354
|
+
|
|
355
|
+
def stop_all_test_modules_in_test_env(self, env_name: str):
|
|
356
|
+
try:
|
|
357
|
+
test_modules = self.get_test_modules(env_name=env_name)
|
|
358
|
+
if test_modules:
|
|
359
|
+
for tm_name in test_modules.keys():
|
|
360
|
+
self.stop_test_module(tm_name)
|
|
361
|
+
else:
|
|
362
|
+
logger.warning(f'🧪⚠️ test modules not available in "{env_name}" test environment')
|
|
363
|
+
except Exception as e:
|
|
364
|
+
logger.error(f'🧪❌ failed to stop all test modules in "{env_name}" test environment. {e}')
|
|
365
|
+
|
|
366
|
+
def execute_all_test_environments(self):
|
|
367
|
+
try:
|
|
368
|
+
test_environments = self.get_test_environments()
|
|
369
|
+
if len(test_environments) > 0:
|
|
370
|
+
for test_env_name in test_environments.keys():
|
|
371
|
+
logger.info(f'🧐🏃➡️🥱 executing test environment "{test_env_name}". please wait...')
|
|
372
|
+
self.execute_all_test_modules_in_test_env(test_env_name)
|
|
373
|
+
logger.info(f'🧐🧍✔️ completed executing test environment "{test_env_name}"')
|
|
374
|
+
else:
|
|
375
|
+
logger.warning('🧐⚠️ Zero test environments found in configuration')
|
|
376
|
+
except Exception as e:
|
|
377
|
+
logger.error(f'🧐❌ failed to execute all test environments. {e}')
|
|
378
|
+
|
|
379
|
+
def stop_all_test_environments(self):
|
|
380
|
+
try:
|
|
381
|
+
test_environments = self.get_test_environments()
|
|
382
|
+
if len(test_environments) > 0:
|
|
383
|
+
for test_env_name in test_environments.keys():
|
|
384
|
+
logger.info(f'🧐⏹️🥱 stopping test environment "{test_env_name}" execution. please wait...')
|
|
385
|
+
self.stop_all_test_modules_in_test_env(test_env_name)
|
|
386
|
+
logger.info(f'🧐🧍✔️ completed stopping test environment "{test_env_name}"')
|
|
387
|
+
else:
|
|
388
|
+
logger.warning('🧐⚠️ Zero test environments found in configuration')
|
|
389
|
+
except Exception as e:
|
|
390
|
+
logger.error(f'🧐❌ failed to stop all test environments. {e}')
|
|
391
|
+
|
|
392
|
+
def add_database(self, database_file: str, database_channel: int, database_network: Union[str, None]=None) -> bool:
|
|
393
|
+
try:
|
|
394
|
+
if self.app.measurement.running:
|
|
395
|
+
logger.warning("⚠️ Cannot add database while measurement is running. Please stop the measurement first.")
|
|
396
|
+
return False
|
|
397
|
+
else:
|
|
398
|
+
databases = Databases(self.com_object.GeneralSetup.DatabaseSetup.Databases)
|
|
399
|
+
databases_info = {databases.item(index).full_name: databases.item(index) for index in range(1, databases.count + 1)}
|
|
400
|
+
if database_file in databases_info.keys():
|
|
401
|
+
logger.warning(f'⚠️ database "{database_file}" already added')
|
|
402
|
+
return False
|
|
403
|
+
else:
|
|
404
|
+
if database_network:
|
|
405
|
+
database = databases.add_network(database_file, database_network)
|
|
406
|
+
else:
|
|
407
|
+
database = databases.add(database_file)
|
|
408
|
+
wait(0.5)
|
|
409
|
+
database.channel = database_channel
|
|
410
|
+
wait(0.5)
|
|
411
|
+
logger.info(f'📢 database "{database_file}" added successfully to channel {database_channel}')
|
|
412
|
+
return True
|
|
413
|
+
except Exception as e:
|
|
414
|
+
logger.error(f"❌ Error adding database '{database_file}': {e}")
|
|
415
|
+
return False
|
|
416
|
+
|
|
417
|
+
def remove_database(self, database_file: str, database_channel: int) -> bool:
|
|
418
|
+
try:
|
|
419
|
+
if self.app.measurement.running:
|
|
420
|
+
logger.warning("⚠️ Cannot remove database while measurement is running. Please stop the measurement first.")
|
|
421
|
+
return False
|
|
422
|
+
else:
|
|
423
|
+
databases = Databases(self.com_object.GeneralSetup.DatabaseSetup.Databases)
|
|
424
|
+
databases_info = {databases.item(index).full_name: databases.item(index) for index in range(1, databases.count + 1)}
|
|
425
|
+
if database_file not in databases_info.keys():
|
|
426
|
+
logger.warning(f'⚠️ database "{database_file}" not available to remove')
|
|
427
|
+
return False
|
|
428
|
+
else:
|
|
429
|
+
for index in range(1, databases.count + 1):
|
|
430
|
+
database = databases.item(index)
|
|
431
|
+
if (database.full_name == database_file) and (database.channel == database_channel):
|
|
432
|
+
databases.remove(index)
|
|
433
|
+
wait(1)
|
|
434
|
+
logger.info(f'📢 database "{database_file}" removed from channel "{database_channel}"')
|
|
435
|
+
return True
|
|
436
|
+
logger.warning(f'⚠️ unable to remove database "{database_file}" from channel "{database_channel}"')
|
|
437
|
+
return False
|
|
438
|
+
except Exception as e:
|
|
439
|
+
logger.error(f"❌ Error removing database '{database_file}': {e}")
|
|
440
|
+
return False
|
|
441
|
+
|
|
442
|
+
def get_mode(self) -> int:
|
|
443
|
+
logger.info(f"⚙️ CANoe Configuration mode = ({self.mode} - {'Offline mode' if self.mode == 1 else 'Online mode'})")
|
|
444
|
+
return self.mode
|
|
445
|
+
|
|
446
|
+
def set_mode(self, type: int) -> bool:
|
|
447
|
+
try:
|
|
448
|
+
if type in [0, 1]:
|
|
449
|
+
self.mode = type
|
|
450
|
+
logger.info(f"⚙️ CANoe Configuration mode set to ({type} - {'Offline mode' if type == 1 else 'Online mode'})")
|
|
451
|
+
return True
|
|
452
|
+
else:
|
|
453
|
+
logger.warning("⚠️ Invalid mode type. Use 0 for Offline mode and 1 for Online mode.")
|
|
454
|
+
return False
|
|
455
|
+
except Exception as e:
|
|
456
|
+
logger.error(f"❌ Error setting CANoe Configuration mode: {e}")
|
|
457
|
+
return False
|
|
458
|
+
|
|
459
|
+
def get_logging_blocks(self) -> list['Logging']:
|
|
460
|
+
blocks = []
|
|
461
|
+
for i in range(1, self.online_setup.logging_collection.count + 1):
|
|
462
|
+
logging_block = self.online_setup.logging_collection.item(i)
|
|
463
|
+
blocks.append(logging_block)
|
|
464
|
+
return blocks
|
|
465
|
+
|
|
466
|
+
def add_logging_block(self, full_name: str) -> 'Logging':
|
|
467
|
+
return self.online_setup.logging_collection.add(full_name)
|
|
468
|
+
|
|
469
|
+
def remove_logging_block(self, index: int) -> None:
|
|
470
|
+
if index == 0:
|
|
471
|
+
raise ValueError("Logging blocks indexing starts from 1 and not 0.")
|
|
472
|
+
self.online_setup.logging_collection.remove(index)
|
|
473
|
+
|
|
474
|
+
def load_logs_for_exporter(self, logger_index: int) -> None:
|
|
475
|
+
self.online_setup.logging_collection.item(logger_index).exporter.load()
|
|
476
|
+
|
|
477
|
+
def get_symbols(self, logger_index: int) -> list['ExporterSymbol']:
|
|
478
|
+
return self.online_setup.logging_collection.item(logger_index).exporter.symbols
|
|
479
|
+
|
|
480
|
+
def get_messages(self, logger_index: int) -> list['Message']:
|
|
481
|
+
return self.online_setup.logging_collection.item(logger_index).exporter.messages
|
|
482
|
+
|
|
483
|
+
def add_filters_to_exporter(self, logger_index: int, full_names: 'Iterable'):
|
|
484
|
+
expo_filter = self.online_setup.logging_collection.item(logger_index).exporter.filter
|
|
485
|
+
for name in full_names:
|
|
486
|
+
expo_filter.add(name)
|
|
487
|
+
|
|
488
|
+
def start_export(self, logger_index: int):
|
|
489
|
+
self.online_setup.logging_collection.item(logger_index).exporter.save()
|
|
490
|
+
|
|
491
|
+
def start_stop_online_logging_block(self, full_name: str, start_stop: bool) -> bool:
|
|
492
|
+
try:
|
|
493
|
+
logging_blocks = self.get_logging_blocks()
|
|
494
|
+
for logging_block in logging_blocks:
|
|
495
|
+
if logging_block.full_name.lower() == full_name.lower():
|
|
496
|
+
if start_stop:
|
|
497
|
+
logging_block.trigger.start()
|
|
498
|
+
logger.info(f'📢 logging block {full_name} started')
|
|
499
|
+
else:
|
|
500
|
+
logging_block.trigger.stop()
|
|
501
|
+
logger.info(f'📢 logging block {full_name} stopped')
|
|
502
|
+
return True
|
|
503
|
+
logger.warning(f'⚠️ logging block {full_name} not found.')
|
|
504
|
+
return False
|
|
505
|
+
except Exception as e:
|
|
506
|
+
logger.error(f"❌ Error starting/stopping logging block {full_name}. {e}")
|
|
507
|
+
|
|
508
|
+
def set_configuration_modified(self, modified: bool) -> None:
|
|
509
|
+
self.modified = modified
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# TODO: complete implementation of the Environment class
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from py_canoe.helpers.common import logger
|
|
5
|
+
from py_canoe.core.child_elements.environment_group import EnvironmentGroup
|
|
6
|
+
from py_canoe.core.child_elements.environment_info import EnvironmentInfo
|
|
7
|
+
from py_canoe.core.child_elements.environment_variable import EnvironmentVariable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Environment:
|
|
11
|
+
"""
|
|
12
|
+
The Environment object represents the environment variables.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self, app):
|
|
15
|
+
self.com_object = app.com_object.Environment
|
|
16
|
+
|
|
17
|
+
def create_group(self):
|
|
18
|
+
return EnvironmentGroup(self.com_object.CreateGroup())
|
|
19
|
+
|
|
20
|
+
def create_info(self) -> 'EnvironmentInfo':
|
|
21
|
+
return EnvironmentInfo(self.com_object.CreateInfo())
|
|
22
|
+
|
|
23
|
+
def get_variable(self, name: str) -> 'EnvironmentVariable':
|
|
24
|
+
return EnvironmentVariable(self.com_object.GetVariable(name))
|
|
25
|
+
|
|
26
|
+
def get_variables(self, vars: list[list[Union[str, int, float]]]) -> list:
|
|
27
|
+
return self.com_object.GetVariables(vars)
|
|
28
|
+
|
|
29
|
+
def set_variables(self, vars: dict):
|
|
30
|
+
self.com_object.SetVariables(vars)
|
|
31
|
+
|
|
32
|
+
def get_environment_variable_value(self, env_var_name: str) -> Union[int, float, str, tuple, None]:
|
|
33
|
+
var_value = None
|
|
34
|
+
try:
|
|
35
|
+
variable = self.get_variable(env_var_name)
|
|
36
|
+
var_value = variable.value if variable.type != 3 else tuple(variable.value)
|
|
37
|
+
logger.info(f'🔢 environment variable({env_var_name}) value = {var_value}')
|
|
38
|
+
except Exception as e:
|
|
39
|
+
logger.error(f"❌ Failed to get environment variable '{env_var_name}': {e}")
|
|
40
|
+
finally:
|
|
41
|
+
return var_value
|
|
42
|
+
|
|
43
|
+
def set_environment_variable_value(self, env_var_name: str, value: Union[int, float, str, tuple]) -> bool:
|
|
44
|
+
try:
|
|
45
|
+
variable = self.get_variable(env_var_name)
|
|
46
|
+
if variable.type == 0:
|
|
47
|
+
converted_value = int(value)
|
|
48
|
+
elif variable.type == 1:
|
|
49
|
+
converted_value = float(value)
|
|
50
|
+
elif variable.type == 2:
|
|
51
|
+
converted_value = str(value)
|
|
52
|
+
else:
|
|
53
|
+
converted_value = tuple(value)
|
|
54
|
+
variable.value = converted_value
|
|
55
|
+
logger.info(f'🔢 environment variable({env_var_name}) set to 👉 {converted_value}')
|
|
56
|
+
return True
|
|
57
|
+
except Exception as e:
|
|
58
|
+
logger.error(f"❌ Failed to set environment variable '{env_var_name}': {e}")
|
|
59
|
+
return False
|