上传初版SDK

This commit is contained in:
2026-06-02 15:21:07 +08:00
parent 842b6aed4f
commit b1acd0155c
28 changed files with 5598 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+257
View File
@@ -0,0 +1,257 @@
# 项目架构
## 整体架构图
```
arxml_sdk/
├── src/ # 源代码
│ ├── __init__.py # 包入口,导出全部公共API
│ ├── core/ # 核心基础设施层
│ │ ├── __init__.py
│ │ ├── base.py # Base 基类
│ │ ├── constants.py # ARXML 标签常量
│ │ └── enums.py # AUTOSAR 枚举类型
│ ├── types/ # 数据类型层
│ │ ├── __init__.py
│ │ ├── base_type.py # 基础数据类型
│ │ ├── unit.py # 单位类型
│ │ ├── data_constraint.py # 数据约束
│ │ ├── compu_method.py # 计算方法
│ │ ├── application_types.py # 应用数据类型
│ │ ├── implementation_types.py # 实现数据类型
│ │ ├── sw_addr_method.py # 软件地址方法
│ │ ├── data_mapping.py # 数据类型映射
│ │ ├── sw_component_type.py # 软件组件类型
│ │ ├── interface.py # 接口定义
│ │ ├── package.py # 包管理
│ │ └── swc_internal_behavior.py # SWC内部行为
│ └── utils/ # 工具层
│ ├── __init__.py
│ └── arxml_writer.py # ARXML文档写入
└── tests/ # 测试
```
## 模块职责
### core 模块 - 核心基础设施层
提供 SDK 运行所需的基础组件,不依赖其他业务模块。
| 文件 | 职责 | 关键类/函数 |
|------|------|-------------|
| base.py | 定义所有类型的基础类 | `Base` (dataclass), `create_uuid()`, `create_text_element()` |
| constants.py | ARXML 标签常量统一管理 | 约140个XML标签常量定义 |
| enums.py | AUTOSAR 枚举类型定义 | `Category`, `Encoding`, `PortDirection` 等12个枚举 |
**Base 类核心属性:**
| 属性 | 类型 | 说明 |
|------|------|------|
| name | str | 元素名称 |
| id | Optional[int] | 元素标识符 |
| parent | Optional[Base] | 父元素引用 |
| description | Optional[str] | 元素描述 |
| package_path | str | 完整包路径 (如 `/Pkg1/Pkg2/Name`) |
**Base 类核心方法:**
| 方法 | 说明 |
|------|------|
| to_arxml(doc) | 抽象方法,将对象序列化为 ARXML DOM 元素 |
| class_name | 属性,获取类型名称 |
| parent_id | 属性,获取父类 ID |
### types 模块 - 数据类型层
实现 AUTOSAR 数据模型的各个类型,依赖 core 模块。
| 文件 | 职责 | 主要类 |
|------|------|--------|
| base_type.py | 基础数据类型 (SW-BASE-TYPE) | `BaseType` |
| unit.py | 数据单位 | `Unit` |
| data_constraint.py | 数据约束范围 | `DataConstraint` |
| compu_method.py | 计算方法 (线性转换/文本表) | `Linear`, `TextTable`, `CompuMethod` |
| application_types.py | 应用层数据类型 | `ApplicationBooleanDataType`, `ApplicationValueDataType`, `ApplicationStructureDataType`, `ApplicationArrayDataType` |
| implementation_types.py | 实现层数据类型 | `ImplementationValueDataType`, `ImplementationStructureDataType`, `ImplementationArrayDataType` |
| sw_addr_method.py | 软件地址方法 | `SwAddrMethod` |
| data_mapping.py | 应用-实现类型映射 | `DataTypeMapping`, `DataTypeMappingSet` |
| sw_component_type.py | 软件组件类型和端口 | `ApplicationSwComponentType`, `RPortPrototype`, `PPortPrototype`, `PRPortPrototype` |
| interface.py | 接口定义 | `SenderReceiverInterface`, `ClientServerInterface`, `ModeSwitchInterface` |
| package.py | AUTOSAR 包 | `Package` |
| swc_internal_behavior.py | SWC 内部行为 | `RunnableEntity`, `TimingEvent`, `InitEvent`, `SwcInternalBehavior` |
### utils 模块 - 工具层
提供 ARXML 文档创建和写入功能。
| 文件 | 职责 | 关键函数 |
|------|------|----------|
| arxml_writer.py | ARXML 文档创建和写入 | `create_arxml_document()`, `write_arxml()`, `write_arxml_pretty()` |
## 类型继承体系
```
Base (core.base)
├── BaseType (types.base_type)
├── Unit (types.unit)
├── DataConstraint (types.data_constraint)
├── CompuMethod (types.compu_method)
│ ├── Linear
│ └── TextTable
├── ApplicationDataType (types.application_types)
│ ├── ApplicationBooleanDataType
│ ├── ApplicationValueDataType
│ ├── ApplicationStructureDataType
│ │ └── StructureElement (内部类)
│ └── ApplicationArrayDataType
│ └── ArrayElement (内部类)
├── ImplementationDataType (types.implementation_types)
│ ├── ImplementationValueDataType
│ ├── ImplementationStructureDataType
│ │ └── StructureElement (内部类)
│ └── ImplementationArrayDataType
│ └── ArrayElement (内部类)
├── SwAddrMethod (types.sw_addr_method)
├── DataTypeMapping (types.data_mapping)
│ └── DataTypeMappingSet
├── SwComponentType (types.sw_component_type)
│ ├── AtomicComponentType
│ │ └── ApplicationSwComponentType
│ └── CompositionSwComponentType
├── PortPrototype (types.sw_component_type)
│ ├── RPortPrototype
│ ├── PPortPrototype
│ └── PRPortPrototype
├── Interface (types.interface)
│ ├── SenderReceiverInterface
│ │ └── DataElement (内部类)
│ ├── ClientServerInterface
│ │ ├── Operation (内部类)
│ │ └── Argument (内部类)
│ ├── ModeSwitchInterface
│ ├── ParameterInterface
│ ├── TriggerInterface
│ └── NvDataInterface
├── Package (types.package)
└── SwcInternalBehavior (types.swc_internal_behavior)
├── RunnableEntity
└── EventType (Union)
├── InitEvent
├── TimingEvent
├── OperationInvokedEvent
└── DataReceivedEvent
```
## 依赖关系图
```
┌─────────────────────────────────────┐
│ arxml_sdk (src/__init__.py) │
│ 导出全部 193 个公共 API 符号 │
└─────────────────────────────────────┘
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ core 模块 │ │ types 模块 │ │ utils 模块 │
│ (基础设施层) │ │ (业务逻辑层) │ │ (工具层) │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ Base 基类 │ │ 数据类型类 │ │ ARXML文档创建 │
│ 常量定义 │◄─────►│ 组件类型类 │ │ ARXML文件写入 │
│ 枚举定义 │ │ 接口定义类 │ │ │
│ UUID/文本工具 │ │ 包管理类 │ │ │
└─────────────────┘ │ 内部行为类 │ └─────────────────┘
└─────────────────┘
┌─────────────────┐
│ tests 模块 │
│ (测试层) │
├─────────────────┤
│ 单元测试 │
│ 集成测试 │
└─────────────────┘
```
**依赖约束:**
- `core` → 无依赖(最底层)
- `types` → 依赖 `core`
- `utils` → 依赖 `core`
- `tests` → 依赖 `src` 所有模块
## 设计模式
### 1. 工厂函数模式
所有类型都配有 `create_xxx()` 工厂函数,简化对象创建:
```python
# 使用工厂函数
uint8 = create_base_type("UInt8", size=8)
# 替代直接实例化(如果存在构造函数)
uint8 = BaseType(name="UInt8", size=8)
```
### 2. 组合模式
通过 `add_xxx()` 方法支持动态添加子元素:
```python
component = ApplicationSwComponentType(name="Sensor")
component.add_port(PPortPrototype(name="DataPort"))
```
### 3. 序列化模式
所有类型都实现 `to_arxml(doc)` 方法,将自身序列化为 ARXML DOM 元素:
```python
element = component.to_arxml(doc)
```
### 4. 数据类模式
使用 `@dataclass` 简化数据类定义:
```python
@dataclass
class BaseType:
name: str
size: int
category: Optional[Category] = None
encoding: Optional[Encoding] = None
```
## 数据流
```
用户代码
创建对象 (工厂函数)
├──► BaseType, ApplicationDataType, SwComponentType 等
序列化 (to_arxml)
├──► XML DOM Element
写入文件 (arxml_writer)
.arxml 文件
```
## 技术栈
| 方面 | 详情 |
|------|------|
| 编程语言 | Python 3 |
| 标准库 | `uuid`, `xml.dom.minidom`, `dataclasses`, `typing`, `enum` |
| 测试框架 | pytest |
| 目标格式 | AUTOSAR ARXML (R4.4 schema) |
| 版本 | 2.0.1 |
+548
View File
@@ -0,0 +1,548 @@
# 使用指南
## 目录
- [快速开始](#快速开始)
- [基础类型创建](#基础类型创建)
- [应用数据类型](#应用数据类型)
- [接口定义](#接口定义)
- [软件组件](#软件组件)
- [内部行为](#内部行为)
- [打包与导出](#打包与导出)
- [完整示例](#完整示例)
---
## 快速开始
### 环境要求
- Python 3.8+
### 安装
`src` 目录添加到 Python 路径即可使用:
```python
import sys
sys.path.insert(0, '/path/to/arxml_sdk/src')
```
或直接使用相对导入:
```python
from src import create_arxml_document, write_arxml
```
### 最小示例
```python
from src import (
create_arxml_document, write_arxml, create_package,
create_base_type, Category, Encoding
)
doc = create_arxml_document()
base_type = create_base_type("UInt8", size=8, encoding=Encoding.TWO_COMPONENT)
package = create_package("MyPackage", elements=[base_type])
package_element = package.to_arxml(doc)
doc.documentElement.appendChild(package_element)
write_arxml(doc, "minimal.arxml")
```
---
## 基础类型创建
### 创建基本整数类型
```python
from src import create_base_type, Category, Encoding
uint8 = create_base_type("UInt8", size=8, encoding=Encoding.TWO_COMPONENT)
uint16 = create_base_type("UInt16", size=16, encoding=Encoding.TWO_COMPONENT)
sint8 = create_base_type("Sint8", size=8, encoding=Encoding.TWO_COMPONENT)
float32 = create_base_type("Float32", size=32, encoding=Encoding.IEEE754)
```
### 创建带文本表的类型
```python
from src import (
create_base_type, create_unit, create_data_constraint,
create_linear, create_text_table, create_compu_method,
Category, LowerSts, UpperSts
)
unit = create_unit("km/h", display="km/h", factor=1.0, offset=0.0)
constraint = create_data_constraint(
"SpeedConstraint",
lower=0, upper=250,
lower_sts=LowerSts.CLOSED,
upper_sts=UpperSts.OPEN
)
linear = create_linear(factor=0.01, offset=0)
compu = create_compu_method(
"SpeedConversion",
unit=unit,
linear=linear,
category=Category.LINEAR
)
value_type = create_value_type(
"Speed",
unit=unit,
compu_method=compu,
data_constraint=constraint
)
```
---
## 应用数据类型
### 布尔类型
```python
from src import create_boolean_type, create_compu_method, create_linear, Category
bool_compu = create_compu_method(
"BoolConversion",
linear=create_linear(factor=1, offset=0),
category=Category.BOOLEAN
)
bool_type = create_boolean_type("ErrorFlag", compu_method=bool_compu)
```
### 值类型
```python
from src import create_value_type, create_unit, create_linear, create_compu_method, Category
unit = create_unit("deg", display="°C")
linear = create_linear(factor=0.1, offset=-40)
compu = create_compu_method("Temperature", unit=unit, linear=linear, category=Category.LINEAR)
temp_type = create_value_type("Temperature", unit=unit, compu_method=compu)
```
### 结构体类型
```python
from src import (
ApplicationStructureDataType, create_value_type,
create_unit, create_linear, create_compu_method
)
unit = create_unit("V")
linear = create_linear(factor=0.001, offset=0)
compu = create_compu_method("Voltage", unit=unit, linear=linear, category=Category.LINEAR)
voltage_type = create_value_type("Voltage", unit=unit, compu_method=compu)
current_type = create_value_type("Current", unit=unit, compu_method=compu)
structure = ApplicationStructureDataType(name="PowerData")
structure.add_element(
ApplicationStructureDataType.StructureElement(name="voltage", data_type=voltage_type, offset=0)
)
structure.add_element(
ApplicationStructureDataType.StructureElement(name="current", data_type=current_type, offset=32)
)
```
### 数组类型
```python
from src import ApplicationArrayDataType, create_value_type, create_unit, Semantic
element_type = create_value_type("SensorValue", unit=create_unit("counts"))
array_type = ApplicationArrayDataType(name="SensorData")
array_type.element = ApplicationArrayDataType.ArrayElement(
length=10,
data_type=element_type,
array_size_semantics=Semantic.FIXED
)
```
---
## 实现数据类型
### 值类型
```python
from src import create_impl_value_type, create_base_type, create_value_type, Encoding
base_type = create_base_type("UInt16", size=16, encoding=Encoding.TWO_COMPONENT)
app_type = create_value_type("AppCounter")
impl_type = create_impl_value_type("ImplCounter", base_type=base_type)
```
### 结构体类型
```python
from src import ImplementationStructureDataType, create_impl_value_type, create_base_type, Encoding
base_u8 = create_base_type("UInt8", size=8, encoding=Encoding.TWO_COMPONENT)
base_u16 = create_base_type("UInt16", size=16, encoding=Encoding.TWO_COMPONENT)
impl_u8 = create_impl_value_type("ImplUInt8", base_type=base_u8)
impl_u16 = create_impl_value_type("ImplUInt16", base_type=base_u16)
struct_type = ImplementationStructureDataType(name="ImplStatus")
struct_type.add_element(
ImplementationStructureDataType.StructureElement(name="status", data_type=impl_u8, offset=0)
)
struct_type.add_element(
ImplementationStructureDataType.StructureElement(name="value", data_type=impl_u16, offset=8)
)
```
### 数组类型
```python
from src import ImplementationArrayDataType, create_impl_value_type, create_base_type, Semantic, Encoding
base = create_base_type("UInt32", size=32, encoding=Encoding.TWO_COMPONENT)
element_type = create_impl_value_type("ImplUInt32", base_type=base)
impl_array = ImplementationArrayDataType(name="ImplBuffer")
impl_array.element = ImplementationArrayDataType.ArrayElement(
length=16,
data_type=element_type,
array_size_semantics=Semantic.FIXED
)
```
---
## 数据类型映射
```python
from src import (
DataTypeMapping, DataTypeMappingSet,
create_value_type, create_impl_value_type, create_base_type, Encoding
)
base = create_base_type("UInt8", size=8, encoding=Encoding.TWO_COMPONENT)
app_type = create_value_type("AppStatus")
impl_type = create_impl_value_type("ImplStatus", base_type=base)
mapping = DataTypeMapping(
name="StatusMapping",
application_data_type=app_type,
implementation_data_type=impl_type
)
mapping_set = DataTypeMappingSet(name="DefaultMappings")
mapping_set.add_mapping(mapping)
```
---
## 接口定义
### 发送-接收接口
```python
from src import (
SenderReceiverInterface, create_sender_receiver_interface,
create_value_type, create_unit, Policy, CalibrationAccess
)
unit = create_unit("km/h")
data_element = SenderReceiverInterface.DataElement(
name="Speed",
data_type=create_value_type("Speed", unit=unit),
policy=Policy.STANDARD,
calibration_access=CalibrationAccess.READ_ONLY
)
interface = create_sender_receiver_interface("SpeedInterface", data_element=data_element)
```
### 客户端-服务端接口
```python
from src import (
ClientServerInterface, create_value_type, create_unit,
PortDirection
)
unit = create_unit("counts")
operation = ClientServerInterface.Operation(
name="Initialize",
is_server=True,
arguments=[
ClientServerInterface.Argument(
name="config",
direction=PortDirection.IN,
data_type=create_value_type("Config", unit=unit)
)
]
)
cs_interface = ClientServerInterface(name="ControlInterface")
cs_interface.add_operation(operation)
```
---
## 软件组件
### 创建组件
```python
from src import (
ApplicationSwComponentType, PPortPrototype, RPortPrototype,
SenderReceiverInterface, create_sender_receiver_interface,
AtomicType, ComponentType
)
interface = create_sender_receiver_interface("DataInterface")
port = PPortPrototype(name="DataPort", interface=interface)
component = ApplicationSwComponentType(
name="SensorComponent",
supports_multiple_instantiation=False,
atomic_type=AtomicType.APPLICATION
)
component.add_port(port)
```
### 创建组合组件
```python
from src import SwComponentType, ComponentType, AtomicComponentType, CompositionSwComponentType
child1 = ApplicationSwComponentType(name="Child1")
child2 = ApplicationSwComponentType(name="Child2")
composition = CompositionSwComponentType(name="Composition")
composition._component_type = ComponentType.COMPOSITION
```
---
## 内部行为
### 创建 Runnable 和事件
```python
from src import (
SwcInternalBehavior, RunnableEntity, TimingEvent, InitEvent,
VariableAccess, create_swc_internal_behavior, create_runnable_entity,
create_timing_event, create_init_event, create_data_received_event
)
runnable = create_runnable_entity(
name="UpdateMeasurement",
symbol="UpdateMeasurement",
minimum_start_interval=0.01
)
runnable.add_variable_access(
VariableAccess(name="SpeedAccess", port_prototype_ref="SpeedPort")
)
timing_event = create_timing_event(name="Timing_10ms", period=0.01)
init_event = InitEvent(name="Init", runnable_ref="UpdateMeasurement")
data_rx_event = create_data_received_event(
name="DataReady",
data_element_ref="ReadyFlag",
period=0.05
)
behavior = create_swc_internal_behavior(
name="SensorBehavior",
runnable_entities=[runnable],
events=[timing_event, init_event, data_rx_event]
)
component = ApplicationSwComponentType(name="Sensor")
component.internal_behavior = behavior
```
---
## 打包与导出
### 基本导出流程
```python
from src import (
create_arxml_document, write_arxml, create_package,
get_ar_packages_element, add_package_to_document,
create_base_type, create_value_type, create_unit
)
doc = create_arxml_document()
packages_element = get_ar_packages_element(doc)
base_type = create_base_type("UInt8", size=8)
app_type = create_value_type("AppData")
package = create_package("MyPkg", elements=[base_type, app_type])
package_element = package.to_arxml(doc)
add_package_to_document(doc, package_element)
write_arxml(doc, "output.arxml")
```
### 格式化输出
```python
from src import write_arxml_pretty
write_arxml_pretty(doc, "output_formatted.arxml")
```
---
## 完整示例
以下示例创建一个完整的 AUTOSAR 软件组件配置:
```python
from src import (
create_arxml_document, write_arxml_pretty, create_package,
get_ar_packages_element, add_package_to_document,
create_base_type, create_unit, create_linear, create_compu_method,
create_value_type, create_impl_value_type,
create_sender_receiver_interface, SenderReceiverInterface,
ApplicationSwComponentType, PPortPrototype, RPortPrototype,
SwcInternalBehavior, RunnableEntity, TimingEvent, InitEvent,
Category, Encoding, AtomicType, Policy, CalibrationAccess,
create_sw_addr_method, SectionType, DataTypeMappingSet, DataTypeMapping
)
doc = create_arxml_document()
base_uint8 = create_base_type("UInt8", size=8, encoding=Encoding.TWO_COMPONENT)
base_uint16 = create_base_type("UInt16", size=16, encoding=Encoding.TWO_COMPONENT)
kmh_unit = create_unit("kmh", display="km/h", factor=1.0, offset=0.0)
speed_linear = create_linear(factor=0.01, offset=0)
speed_compu = create_compu_method("SpeedCompu", unit=kmh_unit, linear=speed_linear, category=Category.LINEAR)
app_speed = create_value_type("AppSpeed", unit=kmh_unit, compu_method=speed_compu)
impl_speed = create_impl_value_type("ImplSpeed", base_type=base_uint16)
mapping = DataTypeMapping(
name="SpeedMapping",
application_data_type=app_speed,
implementation_data_type=impl_speed
)
mapping_set = DataTypeMappingSet(name="SpeedMappingSet")
mapping_set.add_mapping(mapping)
data_element = SenderReceiverInterface.DataElement(
name="SpeedData",
data_type=app_speed,
policy=Policy.STANDARD,
calibration_access=CalibrationAccess.READ_WRITE
)
speed_interface = create_sender_receiver_interface("SpeedInterface", data_element=data_element)
code_method = create_sw_addr_method("CODE", section_type=SectionType.CODE)
runnable = RunnableEntity(
name="UpdateSpeed",
symbol="UpdateSpeed",
minimum_start_interval=0.01,
can_be_invoked_concurrently=False
)
runnable.add_variable_access(
VariableAccess(name="SpeedAccess", port_prototype_ref="SpeedPort")
)
timing = TimingEvent(name="Timing_10ms", period=0.01)
init = InitEvent(name="Init", runnable_ref="UpdateSpeed")
behavior = SwcInternalBehavior(
name="SpeedSensorBehavior",
runnable_entities=[runnable],
events=[timing, init],
symbol="SpeedSensor"
)
port = PPortPrototype(name="SpeedPort", interface=speed_interface)
component = ApplicationSwComponentType(
name="SpeedSensorComponent",
supports_multiple_instantiation=False,
atomic_type=AtomicType.APPLICATION,
internal_behavior=behavior
)
component.add_port(port)
package = create_package("SpeedSensorPkg", elements=[
base_uint8,
base_uint16,
kmh_unit,
app_speed,
impl_speed,
mapping_set,
speed_interface,
code_method,
component
])
package_element = package.to_arxml(doc)
add_package_to_document(doc, package_element)
write_arxml_pretty(doc, "SpeedSensor.arxml")
print("Generated: SpeedSensor.arxml")
```
---
## 常见问题
### Q: 如何创建多个端口?
```python
interface1 = create_sender_receiver_interface("DataInterface")
interface2 = create_sender_receiver_interface("StatusInterface")
component = ApplicationSwComponentType(name="MyComponent")
component.add_port(PPortPrototype(name="DataPort", interface=interface1))
component.add_port(RPortPrototype(name="StatusPort", interface=interface2))
```
### Q: 如何添加多个 Runnable
```python
behavior = SwcInternalBehavior(name="Behavior")
runnable1 = create_runnable_entity(name="InitRunnable", symbol="Init")
runnable2 = create_runnable_entity(name="MainRunnable", symbol="Main", minimum_start_interval=0.01)
behavior.add_runnable(runnable1)
behavior.add_runnable(runnable2)
component = ApplicationSwComponentType(name="MyComponent")
component.internal_behavior = behavior
```
### Q: 如何创建嵌套结构体?
```python
inner_type = create_value_type("InnerValue")
inner_struct = ApplicationStructureDataType(name="InnerStruct")
inner_struct.add_element(
ApplicationStructureDataType.StructureElement(name="value", data_type=inner_type)
)
outer_struct = ApplicationStructureDataType(name="OuterStruct")
outer_struct.add_element(
ApplicationStructureDataType.StructureElement(name="inner", data_type=inner_struct)
)
```
+193
View File
@@ -0,0 +1,193 @@
"""
arxml_sdk - AUTOSAR ARXML 配置生成 SDK
"""
from .core import (
Base,
create_uuid,
create_text_element,
Category,
Encoding,
CalibrationAccess,
SwCalibrationAccess,
UpperSts,
LowerSts,
ConstraintSpecified,
CompuContents,
ComponentType,
AtomicType,
ImplementationCodeType,
AccessPoint,
PortDirection,
Semantic,
SectionType,
Policy,
)
from .types import (
BaseType,
create_base_type,
Unit,
create_unit,
DataConstraint,
create_data_constraint,
Linear,
TextTable,
CompuMethod,
create_linear,
create_text_table,
create_compu_method,
ApplicationDataType,
ApplicationBooleanDataType,
ApplicationValueDataType,
ApplicationStructureDataType,
ApplicationArrayDataType,
create_boolean_type,
create_value_type,
create_structure_type,
create_array_type,
ImplementationDataType,
ImplementationValueDataType,
ImplementationStructureDataType,
ImplementationArrayDataType,
create_impl_value_type,
create_impl_structure_type,
create_impl_array_type,
SwAddrMethod,
create_sw_addr_method,
DataTypeMapping,
DataTypeMappingSet,
create_data_type_mapping,
create_data_type_mapping_set,
SwComponentType,
AtomicComponentType,
CompositionSwComponentType,
ApplicationSwComponentType,
PortPrototype,
RPortPrototype,
PPortPrototype,
PRPortPrototype,
Interface,
SenderReceiverInterface,
ClientServerInterface,
ModeSwitchInterface,
ParameterInterface,
TriggerInterface,
NvDataInterface,
create_sender_receiver_interface,
Package,
create_package,
SwcInternalBehavior,
RunnableEntity,
VariableAccess,
InitEvent,
TimingEvent,
OperationInvokedEvent,
DataReceivedEvent,
create_runnable_entity,
create_timing_event,
create_init_event,
create_operation_invoked_event,
create_data_received_event,
create_swc_internal_behavior,
)
from .utils import (
create_arxml_document,
write_arxml,
write_arxml_pretty,
get_ar_packages_element,
add_package_to_document,
)
__version__ = "2.0.1"
__all__ = [
"Base",
"create_uuid",
"create_text_element",
"Category",
"Encoding",
"CalibrationAccess",
"SwCalibrationAccess",
"UpperSts",
"LowerSts",
"ConstraintSpecified",
"CompuContents",
"ComponentType",
"AtomicType",
"ImplementationCodeType",
"AccessPoint",
"PortDirection",
"Semantic",
"SectionType",
"Policy",
"BaseType",
"create_base_type",
"Unit",
"create_unit",
"DataConstraint",
"create_data_constraint",
"Linear",
"TextTable",
"CompuMethod",
"create_linear",
"create_text_table",
"create_compu_method",
"ApplicationDataType",
"ApplicationBooleanDataType",
"ApplicationValueDataType",
"ApplicationStructureDataType",
"ApplicationArrayDataType",
"create_boolean_type",
"create_value_type",
"create_structure_type",
"create_array_type",
"ImplementationDataType",
"ImplementationValueDataType",
"ImplementationStructureDataType",
"ImplementationArrayDataType",
"create_impl_value_type",
"create_impl_structure_type",
"create_impl_array_type",
"SwAddrMethod",
"create_sw_addr_method",
"DataTypeMapping",
"DataTypeMappingSet",
"create_data_type_mapping",
"create_data_type_mapping_set",
"SwComponentType",
"AtomicComponentType",
"CompositionSwComponentType",
"ApplicationSwComponentType",
"PortPrototype",
"RPortPrototype",
"PPortPrototype",
"PRPortPrototype",
"Interface",
"SenderReceiverInterface",
"ClientServerInterface",
"ModeSwitchInterface",
"ParameterInterface",
"TriggerInterface",
"NvDataInterface",
"create_sender_receiver_interface",
"Package",
"create_package",
"create_arxml_document",
"write_arxml",
"write_arxml_pretty",
"get_ar_packages_element",
"add_package_to_document",
"SwcInternalBehavior",
"RunnableEntity",
"VariableAccess",
"InitEvent",
"TimingEvent",
"OperationInvokedEvent",
"DataReceivedEvent",
"create_runnable_entity",
"create_timing_event",
"create_init_event",
"create_operation_invoked_event",
"create_data_received_event",
"create_swc_internal_behavior",
]
+45
View File
@@ -0,0 +1,45 @@
"""
core 模块
"""
from .base import Base, create_uuid, create_text_element
from .constants import *
from .enums import (
Category,
Encoding,
CalibrationAccess,
SwCalibrationAccess,
UpperSts,
LowerSts,
ConstraintSpecified,
CompuContents,
ComponentType,
AtomicType,
ImplementationCodeType,
AccessPoint,
PortDirection,
Semantic,
SectionType,
Policy,
)
__all__ = [
"Base",
"create_uuid",
"create_text_element",
"Category",
"Encoding",
"CalibrationAccess",
"SwCalibrationAccess",
"UpperSts",
"LowerSts",
"ConstraintSpecified",
"CompuContents",
"ComponentType",
"AtomicType",
"ImplementationCodeType",
"AccessPoint",
"PortDirection",
"Semantic",
"SectionType",
"Policy",
]
+57
View File
@@ -0,0 +1,57 @@
"""
核心基类和工具函数模块
"""
import uuid
import re
import xml.dom.minidom as Dom
from dataclasses import dataclass, field
from typing import Optional, List
from .constants import UUID, SHORT_NAME
from .enums import Category, Encoding, CalibrationAccess, UpperSts, LowerSts
def create_uuid() -> str:
"""生成 UUID"""
return str(uuid.uuid4())
def create_text_element(doc: Dom.Document, tag: str, text: str) -> Dom.Element:
"""创建文本元素"""
element = doc.createElement(tag)
node = doc.createTextNode(text)
element.appendChild(node)
return element
@dataclass
class Base:
"""所有类的基类,提供名称和层级结构支持"""
name: str
id: Optional[int] = field(default=None)
parent: Optional['Base'] = field(default=None, repr=False)
description: Optional[str] = field(default=None)
@property
def class_name(self) -> str:
"""获取类型名称"""
return self.__class__.__name__
@property
def parent_id(self) -> Optional[int]:
"""获取父类ID"""
return self.parent.id if self.parent is not None else None
@property
def package_path(self) -> str:
"""获取完整路径(包路径+名称)"""
path = []
current = self
while current is not None:
path.append(current.name)
current = current.parent
return '/' + '/'.join(reversed(path))
def to_arxml(self, doc: Dom.Document) -> Dom.Element:
"""转换为 ARXML 元素"""
raise NotImplementedError("to_arxml method must be implemented by subclass")
+138
View File
@@ -0,0 +1,138 @@
"""
AUTOSAR ARXML 标签常量统一管理模块
"""
UUID = "UUID"
AR_PACKAGE = "AR-PACKAGE"
AR_PACKAGES = "AR-PACKAGES"
ELEMENT = "ELEMENT"
ELEMENTS = "ELEMENTS"
CATEGORY = "CATEGORY"
SHORT_NAME = "SHORT-NAME"
DEST = "DEST"
UNIT = "UNIT"
UNIT_REF = "UNIT-REF"
COMPU_METHOD = "COMPU-METHOD"
COMPU_METHOD_REF = "COMPU-METHOD-REF"
DATA_CONSTR = "DATA-CONSTR"
DATA_CONSTR_REF = "DATA-CONSTR-REF"
TYPE_TREF = "TYPE-TREF"
SW_BASE_TYPE = "SW-BASE-TYPE"
BASE_TYPE_REF = "BASE-TYPE-REF"
IMPLEMENTATION_DATA_TYPE_REF = "IMPLEMENTATION-DATA-TYPE-REF"
APPLICATION_DATA_TYPE_REF = "APPLICATION-DATA-TYPE-REF"
IS_SERVICE = "IS-SERVICE"
SENDER_RECEIVER_INTERFACE = "SENDER-RECEIVER-INTERFACE"
APPLICATION_SW_COMPONENT_TYPE = "APPLICATION-SW-COMPONENT-TYPE"
PORTS = "PORTS"
R_PORT_PROTOTYPE = "R-PORT-PROTOTYPE"
P_PORT_PROTOTYPE = "P-PORT-PROTOTYPE"
REQUIRED_COM_SPECS = "REQUIRED-COM-SPECS"
PROVIDED_COM_SPECS = "PROVIDED-COM-SPECS"
PROVIDED_INTERFACE_TREF = "PROVIDED-INTERFACE-TREF"
REQUIRED_INTERFACE_TREF = "REQUIRED-INTERFACE-TREF"
NONQUEUED_SENDER_COM_SPEC = "NONQUEUED-SENDER-COM-SPEC"
NONQUEUED_RECEIVER_COM_SPEC = "NONQUEUED-RECEIVER-COM-SPEC"
FIELDS = "FIELDS"
TYPE_REF = "TYPE-REF"
VARIABLE_DATA_PROTOTYPE = "VARIABLE-DATA-PROTOTYPE"
PORT_REF = "PORT-REF"
ENABLE_TAKE_ADDRESS = "ENABLE-TAKE-ADDRESS"
ERROR_HANDLING = "ERROR-HANDLING"
INDIRECT_API = "INDIRECT-API"
ARRAY_VALUE_SPECIFICATION = "ARRAY-VALUE-SPECIFICATION"
RECORD_VALUE_SPECIFICATION = "RECORD-VALUE-SPECIFICATION"
NUMERICAL_VALUE_SPECIFICATION = "NUMERICAL-VALUE-SPECIFICATION"
DATA_ELEMENT_REF = "DATA-ELEMENT-REF"
HANDLE_OUT_OF_RANGE = "HANDLE-OUT-OF-RANGE"
USES_END_TO_END_PROTECTION = "USES-END-TO-END-PROTECTION"
ALIVE_TIMEOUT = "ALIVE-TIMEOUT"
ENABLE_UPDATE = "ENABLE-UPDATE"
HANDLE_NEVER_RECEIVED = "HANDLE-NEVER-RECEIVED"
HANDLE_TIMEOUT_TYPE = "HANDLE-TIMEOUT-TYPE"
INIT_VALUE = "INIT-VALUE"
APPLICATION_VALUE_SPECIFICATION = "APPLICATION-VALUE-SPECIFICATION"
SHORT_LABEL = "SHORT-LABEL"
SW_VALUE_CONT = "SW-VALUE-CONT"
SW_VALUES_PHYS = "SW-VALUES-PHYS"
INTERNAL_BEHAVIORS = "INTERNAL-BEHAVIORS"
SWC_INTERNAL_BEHAVIOR = "SWC-INTERNAL-BEHAVIOR"
DATA_TYPE_MAPPING_REF = "DATA-TYPE-MAPPING-REF"
DATA_TYPE_MAPPING_REFS = "DATA-TYPE-MAPPING-REFS"
EVENTS = "EVENTS"
PERIOD = "PERIOD"
SW_ADDR_METHOD_REF = "SW-ADDR-METHOD-REF"
CLIENT_SERVER_OPERATION_REF = "CLIENT-SERVER-OPERATION-REF"
INIT_EVENT = "INIT-EVENT"
TIMING_EVENT = "TIMING-EVENT"
START_ON_EVENT_REF = "START-ON-EVENT-REF"
PORT_API_OPTIONS = "PORT-API-OPTIONS"
PORT_API_OPTION = "PORT-API-OPTION"
HANDLE_TERMINATION_AND_RESTART = "HANDLE-TERMINATION-AND-RESTART"
SYMBOL = "SYMBOL"
RUNNABLES = "RUNNABLES"
RUNNABLE_ENTITY = "RUNNABLE-ENTITY"
MINIMUM_START_INTERVAL = "MINIMUM-START-INTERVAL"
CAN_BE_INVOKED_CONCURRENTLY = "CAN-BE-INVOKED-CONCURRENTLY"
DATA_RECEIVE_POINT_BY_ARGUMENTS = "DATA-RECEIVE-POINT-BY-ARGUMENTS"
VARIABLE_ACCESS = "VARIABLE-ACCESS"
ACCESSED_VARIABLE = "ACCESSED-VARIABLE"
AUTOSAR_VARIABLE_IREF = "AUTOSAR-VARIABLE-IREF"
PORT_PROTOTYPE_REF = "PORT-PROTOTYPE-REF"
TARGET_DATA_PROTOTYPE_REF = "TARGET-DATA-PROTOTYPE-REF"
DATA_SEND_POINTS = "DATA-SEND-POINTS"
SW_DATA_DEF_PROPS = "SW-DATA-DEF-PROPS"
SW_DATA_DEF_PROPS_VARIANTS = "SW-DATA-DEF-PROPS-VARIANTS"
SW_DATA_DEF_PROPS_CONDITIONAL = "SW-DATA-DEF-PROPS-CONDITIONAL"
SW_CALIBRATION_ACCESS = "SW-CALIBRATION-ACCESS"
SW_IMPL_POLICY = "SW-IMPL-POLICY"
SWC_IMPLEMENTATION = "SWC-IMPLEMENTATION"
CODE = "CODE"
CODE_DESCRIPTORS = "CODE-DESCRIPTORS"
BEHAVIOR_REF = "BEHAVIOR-REF"
AUTOSAR_ENGINEERING_OBJECT = "AUTOSAR-ENGINEERING-OBJECT"
ARTIFACT_DESCRIPTORS = "ARTIFACT-DESCRIPTORS"
SW_ADDR_METHOD = "SW-ADDR-METHOD"
SECTION_TYPE = "SECTION-TYPE"
APPLICATION_PRIMITIVE_DATA_TYPE = "APPLICATION-PRIMITIVE-DATA-TYPE"
APPLICATION_RECORD_DATA_TYPE = "APPLICATION-RECORD-DATA-TYPE"
APPLICATION_ARRAY_DATA_TYPE = "APPLICATION-ARRAY-DATA-TYPE"
ARRAY_SIZE = "ARRAY-SIZE"
ARRAY_SIZE_SEMANTICS = "ARRAY-SIZE-SEMANTICS"
MAX_NUMBER_OF_ELEMENTS = "MAX-NUMBER-OF-ELEMENTS"
PHYS_CONSTRS = "PHYS-CONSTRS"
DATA_CONSTR_RULE = "DATA-CONSTR-RULE"
DATA_CONSTR_RULES = "DATA-CONSTR-RULES"
LOWER_LIMIT = "LOWER-LIMIT"
UPPER_LIMIT = "UPPER-LIMIT"
V = "V"
VT = "VT"
COMPU_INTERNAL_TO_PHYS = "COMPU-INTERNAL-TO-PHYS"
COMPU_SCALES = "COMPU-SCALES"
COMPU_SCALE = "COMPU-SCALE"
COMPU_CONST = "COMPU-CONST"
INTERVAL_TYPE = "INTERVAL-TYPE"
COMPU_NUMERATOR = "COMPU-NUMERATOR"
COMPU_DENOMINATOR = "COMPU-DENOMINATOR"
COMPU_RATIONAL_COEFFS = "COMPU-RATIONAL-COEFFS"
IMPLEMENTATION_DATA_TYPE = "IMPLEMENTATION-DATA-TYPE"
IMPLEMENTATION_DATA_TYPE_ELEMENT = "IMPLEMENTATION-DATA-TYPE-ELEMENT"
SUB_ELEMENTS = "SUB-ELEMENTS"
BASE_TYPE_SIZE = "BASE-TYPE-SIZE"
BASE_TYPE_ENCODING = "BASE-TYPE-ENCODING"
NATIVE_DECLARATION = "NATIVE-DECLARATION"
FACTOR_SI_TO_UNIT = "FACTOR-SI-TO-UNIT"
OFFSET_SI_TO_UNIT = "OFFSET-SI-TO-UNIT"
DATA_TYPE_MAPPING_SET = "DATA-TYPE-MAPPING-SET"
DATA_TYPE_MAPS = "DATA-TYPE-MAPS"
DATA_TYPE_MAP = "DATA-TYPE-MAP"
AUTOSAR = "AUTOSAR"
APPLICATION_RECORD_ELEMENT = "APPLICATION-RECORD-ELEMENT"
DATA_ELEMENTS = "DATA-ELEMENTS"
CLIENT_SERVER_INTERFACE = "CLIENT-SERVER-INTERFACE"
CLIENT_SERVER_OPERATION = "CLIENT-SERVER-OPERATION"
ARGUMENT = "ARGUMENT"
APPLICATION_PRIMITIVE_TYPE_REF = "APPLICATION-PRIMITIVE-TYPE-REF"
DIRECTION = "DIRECTION"
OPERATION_INVOKED_EVENT = "OPERATION-INVOKED-EVENT"
DATA_RECEIVED_EVENT = "DATA-RECEIVED-EVENT"
+135
View File
@@ -0,0 +1,135 @@
"""
AUTOSAR 枚举类型统一管理模块
"""
from enum import Enum, auto
class Category(Enum):
"""数据分类类型"""
FIXED_LENGTH = auto()
IDENTICAL = auto()
TEXT_TABLE = auto()
LINEAR = auto()
BOOLEAN = auto()
VALUE = auto()
STRUCTURE = auto()
ARRAY = auto()
SCALE_LINEAR_AND_TEXT_TABLE = auto()
BITFIELD_TEXT_TABLE = auto()
SCALE_LINEAR = auto()
RECORD = auto()
UNION = auto()
DATA_REFERENCE = auto()
TYPE_REFERENCE = auto()
class Encoding(Enum):
"""数据编码格式"""
ONE_COMPONENT = "1C - One's Complement"
TWO_COMPONENT = "2C - Two's Complement"
BCD_P = "BCD-p - Packed Binary Coded Decimals"
BCD_UP = "BCD-Up - Unpacked Binary Coded Decimals"
DSP_FRACTIONAL = "DSP-FRACTIONAL - Digital Signal Processor"
SM = "SM - Sign Magnitude"
IEEE754 = "IEEE754 - Floating Point"
ISO_8859_1 = "ISO-8859-1 - ASCII-Strings"
ISO_8859_2 = "ISO-8859-2 - ASCII-Strings"
WINDOWS_1252 = "Windows-1252 - ASCII Strings"
UTF_8 = "UTF-8 - UCS Transformation Format 8"
UCS_2 = "UCS-2 - Universal Character Set 2"
NONE = "NONE - Unsigned Integer"
VOID = "VOID - C Language"
BOOLEAN = "BOOLEAN - Logical Type"
UTF_16 = "UTF-16: Character encoding for Unicode code points"
class CalibrationAccess(Enum):
"""校准访问权限"""
READ_ONLY = 'Read-Only'
NOT_ACCESSIBLE = 'Not Accessible'
READ_WRITE = 'Read-Write'
NOT_SPECIFIED = 'Not Specified'
class SwCalibrationAccess(Enum):
"""校准访问权限(同 CalibrationAccess,保持向后兼容)"""
ReadOnly = 'Read-Only'
NotAccessible = 'Not Accessible'
ReadWrite = 'Read-Write'
NotSpecified = 'Not Specified'
class UpperSts(Enum):
"""上限区间状态"""
CLOSED = '['
OPEN = ']'
class LowerSts(Enum):
"""下限区间状态"""
CLOSED = ']'
OPEN = '['
class ConstraintSpecified(Enum):
"""约束指定类型"""
PHYSICAL = auto()
INTERNAL = auto()
class CompuContents(Enum):
"""转换内容方向"""
USE_INTERNAL_TO_PHYSICAL = auto()
USE_PHYSICAL_TO_INTERNAL = auto()
class ComponentType(Enum):
"""组件类型"""
COMPOSITION = auto()
ATOMIC = auto()
class AtomicType(Enum):
"""原子组件类型"""
APPLICATION = "Application"
SENSOR_ACTUATOR = "SensorActuator"
HARDWARE_ABSTRACTION = "I/O - Hardware Abstraction (application layer)"
COMPLEX_DRIVER = "Complex Driver (application layer)"
SERVICE_PROXY = "Service Proxy"
class ImplementationCodeType(Enum):
"""实现代码类型"""
SOURCE_CODE = auto()
OBJECT_CODE = auto()
class AccessPoint(Enum):
"""访问点"""
READ = auto()
WRITE = auto()
class PortDirection(Enum):
"""端口方向"""
IN = auto()
OUT = auto()
class Semantic(Enum):
"""语义/数组大小语义"""
FIXED = 'FIXED-SIZE'
VARIABLE = 'Variable'
class SectionType(Enum):
"""段类型"""
CODE = auto()
DATA = auto()
CONST = auto()
class Policy(Enum):
"""数据策略"""
STANDARD = auto()
EXTENDED = auto()
+141
View File
@@ -0,0 +1,141 @@
"""
types 模块 - 数据类型统一管理
"""
from .base_type import BaseType, create_base_type
from .unit import Unit, create_unit
from .data_constraint import DataConstraint, create_data_constraint
from .compu_method import (
Linear, TextTable, CompuMethod,
create_linear, create_text_table, create_compu_method
)
from .application_types import (
ApplicationDataType,
ApplicationBooleanDataType,
ApplicationValueDataType,
ApplicationStructureDataType,
ApplicationArrayDataType,
create_boolean_type,
create_value_type,
create_structure_type,
create_array_type,
)
from .implementation_types import (
ImplementationDataType,
ImplementationValueDataType,
ImplementationStructureDataType,
ImplementationArrayDataType,
create_impl_value_type,
create_impl_structure_type,
create_impl_array_type,
)
from .sw_addr_method import SwAddrMethod, create_sw_addr_method
from .data_mapping import (
DataTypeMapping,
DataTypeMappingSet,
create_data_type_mapping,
create_data_type_mapping_set,
)
from .sw_component_type import (
SwComponentType,
AtomicComponentType,
CompositionSwComponentType,
ApplicationSwComponentType,
PortPrototype,
RPortPrototype,
PPortPrototype,
PRPortPrototype,
)
from .interface import (
Interface,
SenderReceiverInterface,
ClientServerInterface,
ModeSwitchInterface,
ParameterInterface,
TriggerInterface,
NvDataInterface,
create_sender_receiver_interface,
)
from .package import Package, create_package
from .swc_internal_behavior import (
SwcInternalBehavior,
RunnableEntity,
VariableAccess,
InitEvent,
TimingEvent,
OperationInvokedEvent,
DataReceivedEvent,
create_runnable_entity,
create_timing_event,
create_init_event,
create_operation_invoked_event,
create_data_received_event,
create_swc_internal_behavior,
)
__all__ = [
"BaseType",
"create_base_type",
"Unit",
"create_unit",
"DataConstraint",
"create_data_constraint",
"Linear",
"TextTable",
"CompuMethod",
"create_linear",
"create_text_table",
"create_compu_method",
"ApplicationDataType",
"ApplicationBooleanDataType",
"ApplicationValueDataType",
"ApplicationStructureDataType",
"ApplicationArrayDataType",
"create_boolean_type",
"create_value_type",
"create_structure_type",
"create_array_type",
"ImplementationDataType",
"ImplementationValueDataType",
"ImplementationStructureDataType",
"ImplementationArrayDataType",
"create_impl_value_type",
"create_impl_structure_type",
"create_impl_array_type",
"SwAddrMethod",
"create_sw_addr_method",
"DataTypeMapping",
"DataTypeMappingSet",
"create_data_type_mapping",
"create_data_type_mapping_set",
"SwComponentType",
"AtomicComponentType",
"CompositionSwComponentType",
"ApplicationSwComponentType",
"PortPrototype",
"RPortPrototype",
"PPortPrototype",
"PRPortPrototype",
"Interface",
"SenderReceiverInterface",
"ClientServerInterface",
"ModeSwitchInterface",
"ParameterInterface",
"TriggerInterface",
"NvDataInterface",
"create_sender_receiver_interface",
"Package",
"create_package",
"SwcInternalBehavior",
"RunnableEntity",
"VariableAccess",
"InitEvent",
"TimingEvent",
"OperationInvokedEvent",
"DataReceivedEvent",
"create_runnable_entity",
"create_timing_event",
"create_init_event",
"create_operation_invoked_event",
"create_data_received_event",
"create_swc_internal_behavior",
]
+273
View File
@@ -0,0 +1,273 @@
"""
应用数据类型模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, TYPE_CHECKING, Union
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
APPLICATION_PRIMITIVE_DATA_TYPE, APPLICATION_RECORD_DATA_TYPE, APPLICATION_ARRAY_DATA_TYPE,
SHORT_NAME, CATEGORY, SW_DATA_DEF_PROPS, SW_DATA_DEF_PROPS_VARIANTS,
SW_DATA_DEF_PROPS_CONDITIONAL, SW_CALIBRATION_ACCESS, COMPU_METHOD_REF, DEST,
COMPU_METHOD, DATA_CONSTR_REF, DATA_CONSTR, UNIT_REF, UNIT, ELEMENTS, ELEMENT,
ARRAY_SIZE_SEMANTICS, MAX_NUMBER_OF_ELEMENTS, TYPE_TREF, APPLICATION_RECORD_ELEMENT
)
from ..core.enums import Category, CalibrationAccess, Semantic
if TYPE_CHECKING:
from .unit import Unit
from .compu_method import CompuMethod
from .data_constraint import DataConstraint
@dataclass
class ApplicationDataType(Base):
"""应用数据类型基类"""
category: Optional[Category] = None
calibration_access: CalibrationAccess = CalibrationAccess.READ_WRITE
@dataclass
class ApplicationBooleanDataType(ApplicationDataType):
"""布尔类型"""
compu_method: Optional['CompuMethod'] = None
data_constraint: Optional['DataConstraint'] = None
category: Category = Category.BOOLEAN
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_PRIMITIVE_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_CALIBRATION_ACCESS, self.calibration_access.value.upper())
)
if self.compu_method is not None:
compu_method_ref = create_text_element(doc, COMPU_METHOD_REF, self.compu_method.package_path)
compu_method_ref.setAttribute(DEST, COMPU_METHOD)
sw_data_def_props_conditional.appendChild(compu_method_ref)
if self.data_constraint is not None:
data_constr_ref = create_text_element(doc, DATA_CONSTR_REF, self.data_constraint.package_path)
data_constr_ref.setAttribute(DEST, DATA_CONSTR)
sw_data_def_props_conditional.appendChild(data_constr_ref)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
return element
@dataclass
class ApplicationValueDataType(ApplicationDataType):
"""值类型(标量值)"""
unit: Optional['Unit'] = None
compu_method: Optional['CompuMethod'] = None
data_constraint: Optional['DataConstraint'] = None
category: Category = Category.VALUE
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_PRIMITIVE_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_CALIBRATION_ACCESS, self.calibration_access.value.upper())
)
if self.unit is not None:
unit_ref = create_text_element(doc, UNIT_REF, self.unit.package_path)
unit_ref.setAttribute(DEST, UNIT)
sw_data_def_props_conditional.appendChild(unit_ref)
if self.compu_method is not None:
compu_method_ref = create_text_element(doc, COMPU_METHOD_REF, self.compu_method.package_path)
compu_method_ref.setAttribute(DEST, COMPU_METHOD)
sw_data_def_props_conditional.appendChild(compu_method_ref)
if self.data_constraint is not None:
data_constr_ref = create_text_element(doc, DATA_CONSTR_REF, self.data_constraint.package_path)
data_constr_ref.setAttribute(DEST, DATA_CONSTR)
sw_data_def_props_conditional.appendChild(data_constr_ref)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
return element
@dataclass
class ApplicationStructureDataType(ApplicationDataType):
"""结构体类型"""
category: Category = Category.STRUCTURE
structure_elements: List['ApplicationStructureDataType.StructureElement'] = field(default_factory=list)
@dataclass
class StructureElement(Base):
"""结构体成员"""
data_type: Optional[ApplicationDataType] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_RECORD_ELEMENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.data_type:
element.appendChild(create_text_element(doc, CATEGORY, self.data_type.category.name))
type_ref = create_text_element(doc, TYPE_TREF, self.data_type.package_path)
type_ref.setAttribute('DEST', APPLICATION_PRIMITIVE_DATA_TYPE)
element.appendChild(type_ref)
return element
def get_element(self, name: str) -> Optional['StructureElement']:
"""根据名称查找成员"""
for element in self.structure_elements:
if element.name == name:
return element
return None
def add_element(self, element: 'StructureElement') -> None:
"""添加结构成员"""
if self.get_element(element.name) is not None:
return
self.structure_elements.append(element)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_RECORD_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_CALIBRATION_ACCESS, self.calibration_access.value.upper())
)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
elements = doc.createElement(ELEMENTS)
for structure_element in self.structure_elements:
elements.appendChild(structure_element.to_arxml(doc))
element.appendChild(elements)
return element
@dataclass
class ApplicationArrayDataType(ApplicationDataType):
"""数组类型"""
category: Category = Category.ARRAY
@dataclass
class ArrayElement(Base):
"""数组成员"""
length: Optional[int] = None
data_type: Optional[ApplicationDataType] = None
array_size_semantics: Semantic = Semantic.FIXED
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(ELEMENT)
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.data_type:
element.appendChild(create_text_element(doc, CATEGORY, self.data_type.category.name))
type_ref = create_text_element(doc, TYPE_TREF, self.data_type.package_path)
type_ref.setAttribute('DEST', APPLICATION_PRIMITIVE_DATA_TYPE)
element.appendChild(type_ref)
element.appendChild(create_text_element(doc, ARRAY_SIZE_SEMANTICS, self.array_size_semantics.value))
element.appendChild(create_text_element(doc, MAX_NUMBER_OF_ELEMENTS, str(self.length or 0)))
return element
element: Optional['ArrayElement'] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_ARRAY_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_CALIBRATION_ACCESS, self.calibration_access.value.upper())
)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
if self.element:
array_element = doc.createElement(ELEMENT)
array_element.appendChild(self.element.to_arxml(doc))
element.appendChild(array_element)
return element
def create_boolean_type(
name: str,
compu_method: Optional['CompuMethod'] = None,
data_constraint: Optional['DataConstraint'] = None,
) -> ApplicationBooleanDataType:
"""创建布尔类型的工厂函数"""
return ApplicationBooleanDataType(
name=name,
compu_method=compu_method,
data_constraint=data_constraint,
)
def create_value_type(
name: str,
unit: Optional['Unit'] = None,
compu_method: Optional['CompuMethod'] = None,
data_constraint: Optional['DataConstraint'] = None,
) -> ApplicationValueDataType:
"""创建值类型的工厂函数"""
return ApplicationValueDataType(
name=name,
unit=unit,
compu_method=compu_method,
data_constraint=data_constraint,
)
def create_structure_type(
name: str,
elements: Optional[List['ApplicationStructureDataType.StructureElement']] = None,
) -> ApplicationStructureDataType:
"""创建结构体类型的工厂函数"""
return ApplicationStructureDataType(
name=name,
structure_elements=elements or [],
)
def create_array_type(
name: str,
element: Optional['ApplicationArrayDataType.ArrayElement'] = None,
) -> ApplicationArrayDataType:
"""创建数组类型的工厂函数"""
return ApplicationArrayDataType(
name=name,
element=element,
)
+57
View File
@@ -0,0 +1,57 @@
"""
基础数据类型模块
"""
from dataclasses import dataclass, field
from typing import Optional
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import SW_BASE_TYPE, SHORT_NAME, CATEGORY, BASE_TYPE_SIZE, BASE_TYPE_ENCODING, NATIVE_DECLARATION
from ..core.enums import Category, Encoding
@dataclass
class BaseType(Base):
"""基础数据类型"""
size: Optional[int] = 8
category: Category = Category.FIXED_LENGTH
encoding: Encoding = Encoding.ONE_COMPONENT
native_description: Optional[str] = None
@property
def encoding_value(self) -> str:
"""获取编码值"""
if self.encoding == Encoding.ONE_COMPONENT:
return "1C"
elif self.encoding == Encoding.TWO_COMPONENT:
return "2C"
return self.encoding.name.upper()
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(SW_BASE_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
element.appendChild(create_text_element(doc, BASE_TYPE_SIZE, str(self.size)))
element.appendChild(create_text_element(doc, BASE_TYPE_ENCODING, self.encoding_value))
if self.native_description:
element.appendChild(create_text_element(doc, NATIVE_DECLARATION, self.native_description))
return element
def create_base_type(
name: str,
size: int = 8,
category: Category = Category.FIXED_LENGTH,
encoding: Encoding = Encoding.ONE_COMPONENT,
native_description: Optional[str] = None,
) -> BaseType:
"""创建基础数据类型的工厂函数"""
return BaseType(
name=name,
size=size,
category=category,
encoding=encoding,
native_description=native_description,
)
+143
View File
@@ -0,0 +1,143 @@
"""
计算方法类型模块
"""
from dataclasses import dataclass, field
from typing import Optional, List
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
COMPU_METHOD, SHORT_NAME, CATEGORY, UNIT_REF, DEST, UNIT,
COMPU_INTERNAL_TO_PHYS, COMPU_SCALES, COMPU_SCALE, COMPU_CONST,
LOWER_LIMIT, UPPER_LIMIT, INTERVAL_TYPE, VT,
COMPU_NUMERATOR, COMPU_DENOMINATOR, COMPU_RATIONAL_COEFFS, V
)
from ..core.enums import Category, CompuContents, LowerSts, UpperSts
from .unit import Unit
@dataclass
class Linear(Base):
"""线性转换"""
factor: Optional[float] = None
offset: Optional[float] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
compu_scale = doc.createElement(COMPU_SCALE)
compu_rational_coeffes = doc.createElement(COMPU_RATIONAL_COEFFS)
compu_numerator = doc.createElement(COMPU_NUMERATOR)
compu_numerator.appendChild(create_text_element(doc, V, str(self.offset or 0)))
compu_numerator.appendChild(create_text_element(doc, V, str(self.factor or 0)))
compu_rational_coeffes.appendChild(compu_numerator)
compu_denominator = doc.createElement(COMPU_DENOMINATOR)
compu_denominator.appendChild(create_text_element(doc, V, '1'))
compu_rational_coeffes.appendChild(compu_denominator)
compu_scale.appendChild(compu_rational_coeffes)
return compu_scale
@dataclass
class TextTable(Base):
"""文本表"""
vt: Optional[str] = None
lower: Optional[int] = None
upper: Optional[int] = None
lower_sts: LowerSts = LowerSts.CLOSED
upper_sts: UpperSts = UpperSts.CLOSED
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
compu_scale = doc.createElement(COMPU_SCALE)
lower_limit = create_text_element(doc, LOWER_LIMIT, str(self.lower or 0))
lower_limit.setAttribute(INTERVAL_TYPE, self.lower_sts.value)
compu_scale.appendChild(lower_limit)
upper_limit = create_text_element(doc, UPPER_LIMIT, str(self.upper or 0))
upper_limit.setAttribute(INTERVAL_TYPE, self.upper_sts.value)
compu_scale.appendChild(upper_limit)
compu_const = doc.createElement(COMPU_CONST)
compu_const.appendChild(create_text_element(doc, VT, self.vt or ''))
compu_scale.appendChild(compu_const)
return compu_scale
@dataclass
class CompuMethod(Base):
"""计算方法"""
unit: Optional[Unit] = None
linear: Optional[Linear] = None
text_tables: List[TextTable] = field(default_factory=list)
category: Category = Category.IDENTICAL
compu_contents: CompuContents = CompuContents.USE_INTERNAL_TO_PHYSICAL
def get_text_table(self, vt: str) -> Optional[TextTable]:
"""根据 vt 查找文本表"""
for text_table in self.text_tables:
if text_table.vt == vt:
return text_table
return None
def add_text_table(self, text_table: TextTable) -> None:
"""添加文本表"""
if self.get_text_table(text_table.vt) is not None:
return
self.text_tables.append(text_table)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(COMPU_METHOD)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name.replace("_", "")))
if self.unit is not None:
unit_ref = create_text_element(doc, UNIT_REF, self.unit.package_path)
unit_ref.setAttribute(DEST, UNIT)
element.appendChild(unit_ref)
compu_internal_to_phys = doc.createElement(COMPU_INTERNAL_TO_PHYS)
compu_scales = doc.createElement(COMPU_SCALES)
for text_table in self.text_tables:
compu_scales.appendChild(text_table.to_arxml(doc))
if self.linear is not None:
compu_scales.appendChild(self.linear.to_arxml(doc))
compu_internal_to_phys.appendChild(compu_scales)
element.appendChild(compu_internal_to_phys)
return element
def create_linear(factor: float, offset: float, name: str = "Linear") -> Linear:
"""创建线性转换的工厂函数"""
return Linear(name=name, factor=factor, offset=offset)
def create_text_table(name: str, vt: str, lower: int = 0, upper: int = 0) -> TextTable:
"""创建文本表的工厂函数"""
return TextTable(name=name, vt=vt, lower=lower, upper=upper)
def create_compu_method(
name: str,
unit: Optional[Unit] = None,
linear: Optional[Linear] = None,
text_tables: Optional[List[TextTable]] = None,
category: Category = Category.IDENTICAL,
) -> CompuMethod:
"""创建计算方法的工厂函数"""
return CompuMethod(
name=name,
unit=unit,
linear=linear,
text_tables=text_tables or [],
category=category,
)
+73
View File
@@ -0,0 +1,73 @@
"""
数据约束类型模块
"""
from dataclasses import dataclass, field
from typing import Optional, Union
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
DATA_CONSTR, SHORT_NAME, DATA_CONSTR_RULES, DATA_CONSTR_RULE,
PHYS_CONSTRS, LOWER_LIMIT, UPPER_LIMIT, UNIT_REF, DEST, UNIT, INTERVAL_TYPE
)
from ..core.enums import UpperSts, LowerSts, ConstraintSpecified
from .unit import Unit
@dataclass
class DataConstraint(Base):
"""数据约束"""
unit: Optional[Unit] = None
lower: Union[int, float] = 0
upper: Union[int, float] = 1
lower_sts: LowerSts = LowerSts.CLOSED
upper_sts: UpperSts = UpperSts.CLOSED
constraint_specified: ConstraintSpecified = ConstraintSpecified.PHYSICAL
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(DATA_CONSTR)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
data_constr_rules = doc.createElement(DATA_CONSTR_RULES)
data_constr_rule = doc.createElement(DATA_CONSTR_RULE)
phys_constrs = doc.createElement(PHYS_CONSTRS)
lower_limit = create_text_element(doc, LOWER_LIMIT, str(self.lower))
lower_limit.setAttribute(INTERVAL_TYPE, self.lower_sts.name.upper())
phys_constrs.appendChild(lower_limit)
upper_limit = create_text_element(doc, UPPER_LIMIT, str(self.upper))
upper_limit.setAttribute(INTERVAL_TYPE, self.upper_sts.name.upper())
phys_constrs.appendChild(upper_limit)
if self.unit is not None:
unit_ref = create_text_element(doc, UNIT_REF, self.unit.package_path)
unit_ref.setAttribute(DEST, UNIT)
phys_constrs.appendChild(unit_ref)
data_constr_rule.appendChild(phys_constrs)
data_constr_rules.appendChild(data_constr_rule)
element.appendChild(data_constr_rules)
return element
def create_data_constraint(
name: str,
lower: Union[int, float] = 0,
upper: Union[int, float] = 1,
lower_sts: LowerSts = LowerSts.CLOSED,
upper_sts: UpperSts = UpperSts.CLOSED,
unit: Optional[Unit] = None,
) -> DataConstraint:
"""创建数据约束的工厂函数"""
return DataConstraint(
name=name,
lower=lower,
upper=upper,
lower_sts=lower_sts,
upper_sts=upper_sts,
unit=unit,
)
+101
View File
@@ -0,0 +1,101 @@
"""
数据类型映射集模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, TYPE_CHECKING
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
DATA_TYPE_MAPPING_SET, DATA_TYPE_MAPS, DATA_TYPE_MAP,
SHORT_NAME, APPLICATION_DATA_TYPE_REF, DEST, APPLICATION_PRIMITIVE_DATA_TYPE,
IMPLEMENTATION_DATA_TYPE_REF, DEST as REF_DEST, IMPLEMENTATION_DATA_TYPE
)
if TYPE_CHECKING:
from .application_types import ApplicationDataType
from .implementation_types import ImplementationDataType
else:
from .application_types import ApplicationDataType as ApplicationDataType
from .implementation_types import ImplementationDataType as ImplementationDataType
@dataclass
class DataTypeMapping(Base):
"""数据类型映射"""
application_data_type: Optional['ApplicationDataType'] = None
implementation_data_type: Optional['ImplementationDataType'] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(DATA_TYPE_MAP)
if self.application_data_type:
app_type_ref = create_text_element(
doc, APPLICATION_DATA_TYPE_REF, self.application_data_type.package_path
)
app_type_ref.setAttribute(DEST, APPLICATION_PRIMITIVE_DATA_TYPE)
element.appendChild(app_type_ref)
if self.implementation_data_type:
impl_type_ref = create_text_element(
doc, IMPLEMENTATION_DATA_TYPE_REF, self.implementation_data_type.package_path
)
impl_type_ref.setAttribute(DEST, IMPLEMENTATION_DATA_TYPE)
element.appendChild(impl_type_ref)
return element
@dataclass
class DataTypeMappingSet(Base):
"""数据类型映射集"""
data_type_mappings: List[DataTypeMapping] = field(default_factory=list)
def get_mapping(self, name: str) -> Optional[DataTypeMapping]:
"""根据名称查找映射"""
for mapping in self.data_type_mappings:
if mapping.name == name:
return mapping
return None
def add_mapping(self, mapping: DataTypeMapping) -> None:
"""添加映射"""
if self.get_mapping(mapping.name) is None:
self.data_type_mappings.append(mapping)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(DATA_TYPE_MAPPING_SET)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
data_type_maps = doc.createElement(DATA_TYPE_MAPS)
for mapping in self.data_type_mappings:
data_type_maps.appendChild(mapping.to_arxml(doc))
element.appendChild(data_type_maps)
return element
def create_data_type_mapping(
name: str,
application_data_type: Optional['ApplicationDataType'] = None,
implementation_data_type: Optional['ImplementationDataType'] = None,
) -> DataTypeMapping:
"""创建数据类型映射的工厂函数"""
return DataTypeMapping(
name=name,
application_data_type=application_data_type,
implementation_data_type=implementation_data_type,
)
def create_data_type_mapping_set(
name: str,
mappings: Optional[List[DataTypeMapping]] = None,
) -> DataTypeMappingSet:
"""创建数据类型映射集的工厂函数"""
return DataTypeMappingSet(
name=name,
data_type_mappings=mappings or [],
)
+218
View File
@@ -0,0 +1,218 @@
"""
实现数据类型模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, TYPE_CHECKING
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
IMPLEMENTATION_DATA_TYPE, IMPLEMENTATION_DATA_TYPE_ELEMENT, SHORT_NAME, CATEGORY,
SW_DATA_DEF_PROPS, SW_DATA_DEF_PROPS_VARIANTS, SW_DATA_DEF_PROPS_CONDITIONAL,
BASE_TYPE_REF, DEST, SW_BASE_TYPE, COMPU_METHOD_REF, COMPU_METHOD,
IMPLEMENTATION_DATA_TYPE_REF, SUB_ELEMENTS, ARRAY_SIZE, ARRAY_SIZE_SEMANTICS
)
from ..core.enums import Category, CalibrationAccess, Semantic
if TYPE_CHECKING:
from .base_type import BaseType
from .compu_method import CompuMethod
from .data_constraint import DataConstraint
@dataclass
class ImplementationDataType(Base):
"""实现数据类型基类"""
category: Optional[Category] = None
calibration_access: CalibrationAccess = CalibrationAccess.NOT_SPECIFIED
@dataclass
class ImplementationValueDataType(ImplementationDataType):
"""值类型(标量值)"""
base_type: Optional['BaseType'] = None
compu_method: Optional['CompuMethod'] = None
data_constraint: Optional['DataConstraint'] = None
category: Category = Category.VALUE
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(IMPLEMENTATION_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
if self.base_type is not None:
base_type_ref = create_text_element(doc, BASE_TYPE_REF, self.base_type.package_path)
base_type_ref.setAttribute(DEST, SW_BASE_TYPE)
sw_data_def_props_conditional.appendChild(base_type_ref)
if self.compu_method is not None:
compu_method_ref = create_text_element(doc, COMPU_METHOD_REF, self.compu_method.package_path)
compu_method_ref.setAttribute(DEST, COMPU_METHOD)
sw_data_def_props_conditional.appendChild(compu_method_ref)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
return element
@dataclass
class ImplementationStructureDataType(ImplementationDataType):
"""结构体类型"""
category: Category = Category.STRUCTURE
structure_elements: List['ImplementationStructureDataType.StructureElement'] = field(default_factory=list)
@dataclass
class StructureElement(Base):
"""结构体成员"""
data_type: Optional[ImplementationDataType] = None
category: Category = Category.TYPE_REFERENCE
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(IMPLEMENTATION_DATA_TYPE_ELEMENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
if self.data_type:
impl_type_ref = create_text_element(
doc, IMPLEMENTATION_DATA_TYPE_REF, self.data_type.package_path
)
impl_type_ref.setAttribute(DEST, IMPLEMENTATION_DATA_TYPE)
sw_data_def_props_conditional.appendChild(impl_type_ref)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
return element
def get_element(self, name: str) -> Optional['StructureElement']:
"""根据名称查找成员"""
for element in self.structure_elements:
if element.name == name:
return element
return None
def add_element(self, element: 'StructureElement') -> None:
"""添加结构成员"""
if self.get_element(element.name) is not None:
return
self.structure_elements.append(element)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(IMPLEMENTATION_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sub_elements = doc.createElement(SUB_ELEMENTS)
for structure_element in self.structure_elements:
sub_elements.appendChild(structure_element.to_arxml(doc))
element.appendChild(sub_elements)
return element
@dataclass
class ImplementationArrayDataType(ImplementationDataType):
"""数组类型"""
category: Category = Category.ARRAY
@dataclass
class ArrayElement(Base):
"""数组成员"""
length: Optional[int] = None
data_type: Optional[ImplementationDataType] = None
category: Category = Category.TYPE_REFERENCE
array_size_semantics: Semantic = Semantic.FIXED
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(IMPLEMENTATION_DATA_TYPE_ELEMENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
element.appendChild(create_text_element(doc, ARRAY_SIZE, str(self.length or 0)))
element.appendChild(create_text_element(doc, ARRAY_SIZE_SEMANTICS, self.array_size_semantics.value))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
if self.data_type:
impl_type_ref = create_text_element(
doc, IMPLEMENTATION_DATA_TYPE_REF, self.data_type.package_path
)
impl_type_ref.setAttribute(DEST, IMPLEMENTATION_DATA_TYPE)
sw_data_def_props_conditional.appendChild(impl_type_ref)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
return element
element: Optional['ArrayElement'] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(IMPLEMENTATION_DATA_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, CATEGORY, self.category.name))
sub_elements = doc.createElement(SUB_ELEMENTS)
if self.element:
sub_elements.appendChild(self.element.to_arxml(doc))
element.appendChild(sub_elements)
return element
def create_impl_value_type(
name: str,
base_type: Optional['BaseType'] = None,
compu_method: Optional['CompuMethod'] = None,
) -> ImplementationValueDataType:
"""创建实现值类型的工厂函数"""
return ImplementationValueDataType(
name=name,
base_type=base_type,
compu_method=compu_method,
)
def create_impl_structure_type(
name: str,
elements: Optional[List['ImplementationStructureDataType.StructureElement']] = None,
) -> ImplementationStructureDataType:
"""创建实现结构体类型的工厂函数"""
return ImplementationStructureDataType(
name=name,
structure_elements=elements or [],
)
def create_impl_array_type(
name: str,
element: Optional['ImplementationArrayDataType.ArrayElement'] = None,
) -> ImplementationArrayDataType:
"""创建实现数组类型的工厂函数"""
return ImplementationArrayDataType(
name=name,
element=element,
)
+196
View File
@@ -0,0 +1,196 @@
"""
接口定义模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, TYPE_CHECKING, Union
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
SENDER_RECEIVER_INTERFACE, SHORT_NAME, IS_SERVICE, DATA_ELEMENTS,
VARIABLE_DATA_PROTOTYPE, CATEGORY, SW_DATA_DEF_PROPS, SW_DATA_DEF_PROPS_VARIANTS,
SW_DATA_DEF_PROPS_CONDITIONAL, SW_CALIBRATION_ACCESS, SW_IMPL_POLICY,
TYPE_TREF, DEST, APPLICATION_PRIMITIVE_DATA_TYPE, APPLICATION_RECORD_DATA_TYPE,
APPLICATION_ARRAY_DATA_TYPE, CLIENT_SERVER_INTERFACE, CLIENT_SERVER_OPERATION,
ARGUMENT, APPLICATION_PRIMITIVE_TYPE_REF, DIRECTION
)
from ..core.enums import Policy, CalibrationAccess
if TYPE_CHECKING:
from .base_type import BaseType
from .compu_method import CompuMethod
from .data_constraint import DataConstraint
from .sw_addr_method import SwAddrMethod
from .application_types import ApplicationDataType
from .implementation_types import ImplementationDataType
TYPE_DEST_MAPPING = {
"ApplicationStructureDataType": APPLICATION_RECORD_DATA_TYPE,
"ApplicationArrayDataType": APPLICATION_ARRAY_DATA_TYPE,
}
@dataclass
class Interface(Base):
"""接口基类"""
is_service: bool = False
@dataclass
class SenderReceiverInterface(Interface):
"""发送-接收接口"""
@dataclass
class DataElement(Base):
"""数据元素"""
sw_addr_method: Optional['SwAddrMethod'] = None
data_constraint: Optional['DataConstraint'] = None
data_type: Optional[Union['ApplicationDataType', 'ImplementationDataType']] = None
policy: Policy = Policy.STANDARD
calibration_access: CalibrationAccess = CalibrationAccess.READ_ONLY
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(VARIABLE_DATA_PROTOTYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.data_type:
element.appendChild(create_text_element(doc, CATEGORY, self.data_type.category.name))
sw_data_def_props = doc.createElement(SW_DATA_DEF_PROPS)
sw_data_def_props_variants = doc.createElement(SW_DATA_DEF_PROPS_VARIANTS)
sw_data_def_props_conditional = doc.createElement(SW_DATA_DEF_PROPS_CONDITIONAL)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_CALIBRATION_ACCESS, self.calibration_access.value.upper())
)
sw_data_def_props_conditional.appendChild(
create_text_element(doc, SW_IMPL_POLICY, self.policy.name.upper())
)
sw_data_def_props_variants.appendChild(sw_data_def_props_conditional)
sw_data_def_props.appendChild(sw_data_def_props_variants)
element.appendChild(sw_data_def_props)
type_dest = TYPE_DEST_MAPPING.get(type(self.data_type).__name__, APPLICATION_PRIMITIVE_DATA_TYPE)
type_tref = create_text_element(doc, TYPE_TREF, self.data_type.package_path)
type_tref.setAttribute(DEST, type_dest)
element.appendChild(type_tref)
return element
data_element: Optional[DataElement] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(SENDER_RECEIVER_INTERFACE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, IS_SERVICE, str(self.is_service).lower()))
if self.data_element:
data_elements = doc.createElement(DATA_ELEMENTS)
data_elements.appendChild(self.data_element.to_arxml(doc))
element.appendChild(data_elements)
return element
@dataclass
class ClientServerInterface(Interface):
"""客户端-服务端接口"""
@dataclass
class Operation(Base):
"""操作方法定义"""
is_server: bool = True
arguments: List['ClientServerInterface.Argument'] = field(default_factory=list)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(CLIENT_SERVER_OPERATION)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, DIRECTION, "SERVER" if self.is_server else "CLIENT"))
return element
@dataclass
class Argument(Base):
"""操作参数定义"""
direction: str = "IN"
data_type: Optional['ApplicationDataType'] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(ARGUMENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, DIRECTION, self.direction))
if self.data_type:
type_ref = create_text_element(doc, APPLICATION_PRIMITIVE_TYPE_REF, self.data_type.package_path)
type_ref.setAttribute(DEST, APPLICATION_PRIMITIVE_DATA_TYPE)
element.appendChild(type_ref)
return element
operations: List[Operation] = field(default_factory=list)
def get_operation(self, name: str) -> Optional['Operation']:
"""根据名称查找操作"""
for op in self.operations:
if op.name == name:
return op
return None
def add_operation(self, operation: 'Operation') -> None:
"""添加操作"""
if self.get_operation(operation.name) is None:
self.operations.append(operation)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(CLIENT_SERVER_INTERFACE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, IS_SERVICE, str(self.is_service).lower()))
for op in self.operations:
element.appendChild(op.to_arxml(doc))
return element
@dataclass
class ModeSwitchInterface(Interface):
"""模式切换接口"""
pass
@dataclass
class ParameterInterface(Interface):
"""参数接口"""
pass
@dataclass
class TriggerInterface(Interface):
"""触发接口"""
pass
@dataclass
class NvDataInterface(Interface):
"""NvData接口"""
pass
def create_sender_receiver_interface(
name: str,
data_element: Optional[SenderReceiverInterface.DataElement] = None,
is_service: bool = False,
) -> SenderReceiverInterface:
"""创建发送-接收接口的工厂函数"""
return SenderReceiverInterface(
name=name,
data_element=data_element,
is_service=is_service,
)
+59
View File
@@ -0,0 +1,59 @@
"""
Package 模块
"""
from dataclasses import dataclass, field
from typing import List, Optional, TYPE_CHECKING
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import AR_PACKAGE, SHORT_NAME, ELEMENTS
if TYPE_CHECKING:
from .base_type import BaseType
from .application_types import ApplicationDataType
from .implementation_types import ImplementationDataType
from .compu_method import CompuMethod
from .data_constraint import DataConstraint
from .data_mapping import DataTypeMappingSet
@dataclass
class Package(Base):
"""AUTOSAR 包"""
elements: List[Base] = field(default_factory=list)
def get_element(self, name: str) -> Optional[Base]:
"""根据名称查找元素"""
for element in self.elements:
if element.name == name:
return element
return None
def add_element(self, element: Base) -> None:
"""添加元素"""
existing = self.get_element(element.name)
if existing is None:
self.elements.append(element)
else:
element.id = existing.id
element.description = existing.description
self.elements.remove(existing)
self.elements.append(element)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(AR_PACKAGE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
elements = doc.createElement(ELEMENTS)
for elem in self.elements:
elements.appendChild(elem.to_arxml(doc))
element.appendChild(elements)
return element
def create_package(name: str, elements: Optional[List[Base]] = None) -> Package:
"""创建包的工厂函数"""
return Package(name=name, elements=elements or [])
+30
View File
@@ -0,0 +1,30 @@
"""
软件地址方法模块
"""
from dataclasses import dataclass, field
from typing import Optional
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import SW_ADDR_METHOD, SHORT_NAME, SECTION_TYPE
from ..core.enums import SectionType
@dataclass
class SwAddrMethod(Base):
"""软件地址方法"""
section_type: Optional[SectionType] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(SW_ADDR_METHOD)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.section_type:
element.appendChild(create_text_element(doc, SECTION_TYPE, self.section_type.name))
return element
def create_sw_addr_method(name: str, section_type: Optional[SectionType] = None) -> SwAddrMethod:
"""创建软件地址方法的工厂函数"""
return SwAddrMethod(name=name, section_type=section_type)
+287
View File
@@ -0,0 +1,287 @@
"""
软件组件类型模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, TYPE_CHECKING
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
APPLICATION_SW_COMPONENT_TYPE, SHORT_NAME, PORTS, R_PORT_PROTOTYPE, P_PORT_PROTOTYPE,
REQUIRED_COM_SPECS, PROVIDED_COM_SPECS, PROVIDED_INTERFACE_TREF, REQUIRED_INTERFACE_TREF,
NONQUEUED_RECEIVER_COM_SPEC, NONQUEUED_SENDER_COM_SPEC, DATA_ELEMENT_REF, VARIABLE_DATA_PROTOTYPE,
DEST, SENDER_RECEIVER_INTERFACE, HANDLE_OUT_OF_RANGE, USES_END_TO_END_PROTECTION,
ALIVE_TIMEOUT, ENABLE_UPDATE, HANDLE_NEVER_RECEIVED, HANDLE_TIMEOUT_TYPE, SW_DATA_DEF_PROPS,
SW_DATA_DEF_PROPS_VARIANTS, SW_DATA_DEF_PROPS_CONDITIONAL, SW_CALIBRATION_ACCESS, SW_IMPL_POLICY,
TYPE_TREF, INTERNAL_BEHAVIORS, SWC_INTERNAL_BEHAVIOR, RUNNABLES, RUNNABLE_ENTITY,
MINIMUM_START_INTERVAL, CAN_BE_INVOKED_CONCURRENTLY, DATA_RECEIVE_POINT_BY_ARGUMENTS,
VARIABLE_ACCESS, ACCESSED_VARIABLE, AUTOSAR_VARIABLE_IREF, PORT_PROTOTYPE_REF,
TARGET_DATA_PROTOTYPE_REF, DATA_SEND_POINTS, EVENTS, INIT_EVENT, TIMING_EVENT,
OPERATION_INVOKED_EVENT, DATA_RECEIVED_EVENT, START_ON_EVENT_REF, PERIOD, CODE,
SW_ADDR_METHOD_REF, CLIENT_SERVER_INTERFACE,
)
from ..core.enums import ComponentType, AtomicType, ImplementationCodeType, CalibrationAccess, Policy
if TYPE_CHECKING:
from .interface import SenderReceiverInterface, ClientServerInterface
from .data_mapping import SwAddrMethod
from .swc_internal_behavior import SwcInternalBehavior
@dataclass
class SwComponentType(Base):
"""软件组件类型基类"""
component_type: ComponentType = ComponentType.ATOMIC
@dataclass
class AtomicComponentType(SwComponentType):
"""原子组件类型"""
supports_multiple_instantiation: bool = True
atomic_type: AtomicType = AtomicType.APPLICATION
implementation_code_type: ImplementationCodeType = ImplementationCodeType.SOURCE_CODE
@dataclass
class CompositionSwComponentType(SwComponentType):
"""组合组件类型"""
component_type: ComponentType = ComponentType.COMPOSITION
@dataclass
class ParameterSwComponentType(SwComponentType):
"""参数组件类型"""
pass
@dataclass
class ApplicationSwComponentType(AtomicComponentType):
"""应用软件组件类型"""
atomic_type: AtomicType = AtomicType.APPLICATION
ports: List['PortPrototype'] = field(default_factory=list)
internal_behavior: Optional['SwcInternalBehavior'] = None
def get_port(self, name: str) -> Optional['PortPrototype']:
"""根据名称查找端口"""
for port in self.ports:
if port.name == name:
return port
return None
def add_port(self, port: 'PortPrototype') -> None:
"""添加端口"""
if self.get_port(port.name) is None:
self.ports.append(port)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(APPLICATION_SW_COMPONENT_TYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.ports:
ports_elem = doc.createElement(PORTS)
for port in self.ports:
ports_elem.appendChild(port.to_arxml(doc))
element.appendChild(ports_elem)
if self.internal_behavior:
internal_behaviors = doc.createElement(INTERNAL_BEHAVIORS)
internal_behaviors.appendChild(self.internal_behavior.to_arxml(doc))
element.appendChild(internal_behaviors)
return element
@dataclass
class ServiceSwComponentType(AtomicComponentType):
"""服务组件类型"""
pass
@dataclass
class SensorActuatorSwComponentType(AtomicComponentType):
"""传感器/执行器组件类型"""
atomic_type: AtomicType = AtomicType.SENSOR_ACTUATOR
@dataclass
class EcuAbstractionSwComponentType(AtomicComponentType):
"""ECU抽象组件类型"""
atomic_type: AtomicType = AtomicType.HARDWARE_ABSTRACTION
@dataclass
class ComplexDeviceDriverSwComponentType(AtomicComponentType):
"""复杂驱动组件类型"""
atomic_type: AtomicType = AtomicType.COMPLEX_DRIVER
@dataclass
class ServiceProxySwComponentType(AtomicComponentType):
"""服务代理组件类型"""
atomic_type: AtomicType = AtomicType.SERVICE_PROXY
@dataclass
class PortPrototype(Base):
"""端口原型基类"""
interface: Optional['SenderReceiverInterface'] = None
@dataclass
class RPortPrototype(PortPrototype):
"""接收端口(R-Port"""
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(R_PORT_PROTOTYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.interface:
required_com_specs = doc.createElement(REQUIRED_COM_SPECS)
nonqueued_receiver_com_spec = doc.createElement(NONQUEUED_RECEIVER_COM_SPEC)
if hasattr(self.interface, 'data_element') and self.interface.data_element:
data_element_ref = create_text_element(
doc, DATA_ELEMENT_REF, self.interface.data_element.package_path
)
data_element_ref.setAttribute(DEST, VARIABLE_DATA_PROTOTYPE)
nonqueued_receiver_com_spec.appendChild(data_element_ref)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_OUT_OF_RANGE, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, USES_END_TO_END_PROTECTION, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, ALIVE_TIMEOUT, '0')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, ENABLE_UPDATE, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_NEVER_RECEIVED, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_TIMEOUT_TYPE, 'NONE')
)
required_com_specs.appendChild(nonqueued_receiver_com_spec)
element.appendChild(required_com_specs)
required_interface_tref = create_text_element(
doc, REQUIRED_INTERFACE_TREF, self.interface.package_path
)
required_interface_tref.setAttribute(DEST, SENDER_RECEIVER_INTERFACE)
element.appendChild(required_interface_tref)
return element
@dataclass
class PPortPrototype(PortPrototype):
"""发送端口(P-Port"""
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(P_PORT_PROTOTYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.interface:
provided_com_specs = doc.createElement(PROVIDED_COM_SPECS)
nonqueued_sender_com_spec = doc.createElement(NONQUEUED_SENDER_COM_SPEC)
if hasattr(self.interface, 'data_element') and self.interface.data_element:
data_element_ref = create_text_element(
doc, DATA_ELEMENT_REF, self.interface.data_element.package_path
)
data_element_ref.setAttribute(DEST, VARIABLE_DATA_PROTOTYPE)
nonqueued_sender_com_spec.appendChild(data_element_ref)
provided_com_specs.appendChild(nonqueued_sender_com_spec)
element.appendChild(provided_com_specs)
provided_interface_tref = create_text_element(
doc, PROVIDED_INTERFACE_TREF, self.interface.package_path
)
provided_interface_tref.setAttribute(DEST, SENDER_RECEIVER_INTERFACE)
element.appendChild(provided_interface_tref)
return element
@dataclass
class PRPortPrototype(PortPrototype):
"""双向端口(PR-Port"""
required_interface: Optional['SenderReceiverInterface'] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(P_PORT_PROTOTYPE)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.interface:
provided_com_specs = doc.createElement(PROVIDED_COM_SPECS)
nonqueued_sender_com_spec = doc.createElement(NONQUEUED_SENDER_COM_SPEC)
if hasattr(self.interface, 'data_element') and self.interface.data_element:
data_element_ref = create_text_element(
doc, DATA_ELEMENT_REF, self.interface.data_element.package_path
)
data_element_ref.setAttribute(DEST, VARIABLE_DATA_PROTOTYPE)
nonqueued_sender_com_spec.appendChild(data_element_ref)
provided_com_specs.appendChild(nonqueued_sender_com_spec)
element.appendChild(provided_com_specs)
provided_interface_tref = create_text_element(
doc, PROVIDED_INTERFACE_TREF, self.interface.package_path
)
provided_interface_tref.setAttribute(DEST, SENDER_RECEIVER_INTERFACE)
element.appendChild(provided_interface_tref)
if self.required_interface:
required_com_specs = doc.createElement(REQUIRED_COM_SPECS)
nonqueued_receiver_com_spec = doc.createElement(NONQUEUED_RECEIVER_COM_SPEC)
if hasattr(self.required_interface, 'data_element') and self.required_interface.data_element:
data_element_ref = create_text_element(
doc, DATA_ELEMENT_REF, self.required_interface.data_element.package_path
)
data_element_ref.setAttribute(DEST, VARIABLE_DATA_PROTOTYPE)
nonqueued_receiver_com_spec.appendChild(data_element_ref)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_OUT_OF_RANGE, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, USES_END_TO_END_PROTECTION, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, ALIVE_TIMEOUT, '0')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, ENABLE_UPDATE, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_NEVER_RECEIVED, 'FALSE')
)
nonqueued_receiver_com_spec.appendChild(
create_text_element(doc, HANDLE_TIMEOUT_TYPE, 'NONE')
)
required_com_specs.appendChild(nonqueued_receiver_com_spec)
element.appendChild(required_com_specs)
required_interface_tref = create_text_element(
doc, REQUIRED_INTERFACE_TREF, self.required_interface.package_path
)
required_interface_tref.setAttribute(DEST, SENDER_RECEIVER_INTERFACE)
element.appendChild(required_interface_tref)
return element
+276
View File
@@ -0,0 +1,276 @@
"""
SWC 内部行为模块
"""
from dataclasses import dataclass, field
from typing import Optional, List, Union, TYPE_CHECKING
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import (
RUNNABLE_ENTITY, SHORT_NAME, MINIMUM_START_INTERVAL, CAN_BE_INVOKED_CONCURRENTLY,
DATA_RECEIVE_POINT_BY_ARGUMENTS, VARIABLE_ACCESS, ACCESSED_VARIABLE, AUTOSAR_VARIABLE_IREF,
PORT_PROTOTYPE_REF, TARGET_DATA_PROTOTYPE_REF, DATA_SEND_POINTS, SYMBOL,
SW_ADDR_METHOD_REF, DATA_ELEMENT_REF, RUNNABLES, EVENTS, INIT_EVENT, TIMING_EVENT,
OPERATION_INVOKED_EVENT, DATA_RECEIVED_EVENT, START_ON_EVENT_REF, PERIOD,
CLIENT_SERVER_OPERATION_REF, DEST, VARIABLE_DATA_PROTOTYPE, SWC_INTERNAL_BEHAVIOR
)
if TYPE_CHECKING:
from .interface import ClientServerInterface
from .sw_addr_method import SwAddrMethod
@dataclass
class VariableAccess(Base):
"""变量访问"""
port_prototype_ref: Optional[str] = None
target_data_prototype_ref: Optional[str] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(ACCESSED_VARIABLE)
autosar_var_iref = doc.createElement(AUTOSAR_VARIABLE_IREF)
if self.port_prototype_ref:
port_ref = create_text_element(doc, PORT_PROTOTYPE_REF, self.port_prototype_ref)
port_ref.setAttribute(DEST, "PORT-PROTOTYPE")
autosar_var_iref.appendChild(port_ref)
if self.target_data_prototype_ref:
target_ref = create_text_element(doc, TARGET_DATA_PROTOTYPE_REF, self.target_data_prototype_ref)
target_ref.setAttribute(DEST, VARIABLE_DATA_PROTOTYPE)
autosar_var_iref.appendChild(target_ref)
element.appendChild(autosar_var_iref)
return element
@dataclass
class RunnableEntity(Base):
"""Runnable 实体"""
minimum_start_interval: int = 0
can_be_invoked_concurrently: bool = False
data_receive_points: List[VariableAccess] = field(default_factory=list)
data_send_points: List[VariableAccess] = field(default_factory=list)
variable_accesses: List[VariableAccess] = field(default_factory=list)
symbol: Optional[str] = None
sw_addr_method_ref: Optional[str] = None
def add_data_receive_point(self, access: VariableAccess) -> None:
"""添加数据接收点"""
self.data_receive_points.append(access)
def add_data_send_point(self, access: VariableAccess) -> None:
"""添加数据发送点"""
self.data_send_points.append(access)
def add_variable_access(self, access: VariableAccess) -> None:
"""添加变量访问"""
self.variable_accesses.append(access)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(RUNNABLE_ENTITY)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, MINIMUM_START_INTERVAL, str(self.minimum_start_interval)))
element.appendChild(create_text_element(doc, CAN_BE_INVOKED_CONCURRENTLY, str(self.can_be_invoked_concurrently).lower()))
if self.symbol:
element.appendChild(create_text_element(doc, SYMBOL, self.symbol))
if self.sw_addr_method_ref:
method_ref = create_text_element(doc, SW_ADDR_METHOD_REF, self.sw_addr_method_ref)
method_ref.setAttribute(DEST, "SW-ADDR-METHOD")
element.appendChild(method_ref)
if self.data_receive_points:
data_receive_elem = doc.createElement(DATA_RECEIVE_POINT_BY_ARGUMENTS)
for access in self.data_receive_points:
data_receive_elem.appendChild(access.to_arxml(doc))
element.appendChild(data_receive_elem)
if self.data_send_points:
data_send_elem = doc.createElement(DATA_SEND_POINTS)
for access in self.data_send_points:
data_send_elem.appendChild(access.to_arxml(doc))
element.appendChild(data_send_elem)
if self.variable_accesses:
var_access_elem = doc.createElement(VARIABLE_ACCESS)
for access in self.variable_accesses:
var_access_elem.appendChild(access.to_arxml(doc))
element.appendChild(var_access_elem)
return element
@dataclass
class InitEvent(Base):
"""初始化事件"""
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(INIT_EVENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
return element
@dataclass
class TimingEvent(Base):
"""定时事件"""
period: float = 0.01
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(TIMING_EVENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, PERIOD, str(self.period)))
return element
@dataclass
class OperationInvokedEvent(Base):
"""操作调用事件"""
operation_ref: Optional[str] = None
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(OPERATION_INVOKED_EVENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.operation_ref:
op_ref = create_text_element(doc, START_ON_EVENT_REF, self.operation_ref)
op_ref.setAttribute(DEST, CLIENT_SERVER_OPERATION_REF)
element.appendChild(op_ref)
return element
@dataclass
class DataReceivedEvent(Base):
"""数据接收事件"""
data_element_ref: Optional[str] = None
period: float = 0.01
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(DATA_RECEIVED_EVENT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
if self.data_element_ref:
data_ref = create_text_element(doc, START_ON_EVENT_REF, self.data_element_ref)
data_ref.setAttribute(DEST, DATA_ELEMENT_REF)
element.appendChild(data_ref)
element.appendChild(create_text_element(doc, PERIOD, str(self.period)))
return element
EventType = Union[InitEvent, TimingEvent, OperationInvokedEvent, DataReceivedEvent]
@dataclass
class SwcInternalBehavior(Base):
"""SWC 内部行为"""
runnable_entities: List[RunnableEntity] = field(default_factory=list)
events: List[EventType] = field(default_factory=list)
symbol: Optional[str] = None
def get_runnable(self, name: str) -> Optional[RunnableEntity]:
"""根据名称查找 Runnable"""
for runnable in self.runnable_entities:
if runnable.name == name:
return runnable
return None
def add_runnable(self, runnable: RunnableEntity) -> None:
"""添加 Runnable"""
if self.get_runnable(runnable.name) is None:
self.runnable_entities.append(runnable)
def get_event(self, name: str) -> Optional[EventType]:
"""根据名称查找事件"""
for event in self.events:
if event.name == name:
return event
return None
def add_event(self, event: EventType) -> None:
"""添加事件"""
if self.get_event(event.name) is None:
self.events.append(event)
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(SWC_INTERNAL_BEHAVIOR)
element.setAttribute("UUID", create_uuid())
if self.symbol:
element.appendChild(create_text_element(doc, SYMBOL, self.symbol))
if self.runnable_entities:
runnables = doc.createElement(RUNNABLES)
for runnable in self.runnable_entities:
runnables.appendChild(runnable.to_arxml(doc))
element.appendChild(runnables)
if self.events:
events_elem = doc.createElement(EVENTS)
for event in self.events:
events_elem.appendChild(event.to_arxml(doc))
element.appendChild(events_elem)
return element
def create_runnable_entity(
name: str,
minimum_start_interval: int = 0,
can_be_invoked_concurrently: bool = False,
symbol: Optional[str] = None,
sw_addr_method_ref: Optional[str] = None,
) -> RunnableEntity:
"""创建 Runnable 实体的工厂函数"""
return RunnableEntity(
name=name,
minimum_start_interval=minimum_start_interval,
can_be_invoked_concurrently=can_be_invoked_concurrently,
symbol=symbol,
sw_addr_method_ref=sw_addr_method_ref,
)
def create_timing_event(name: str, period: float = 0.01) -> TimingEvent:
"""创建定时事件的工厂函数"""
return TimingEvent(name=name, period=period)
def create_init_event(name: str) -> InitEvent:
"""创建初始化事件的工厂函数"""
return InitEvent(name=name)
def create_operation_invoked_event(name: str, operation_ref: Optional[str] = None) -> OperationInvokedEvent:
"""创建操作调用事件的工厂函数"""
return OperationInvokedEvent(name=name, operation_ref=operation_ref)
def create_data_received_event(name: str, data_element_ref: Optional[str] = None, period: float = 0.01) -> DataReceivedEvent:
"""创建数据接收事件的工厂函数"""
return DataReceivedEvent(name=name, data_element_ref=data_element_ref, period=period)
def create_swc_internal_behavior(
name: str,
runnable_entities: Optional[List[RunnableEntity]] = None,
events: Optional[List[EventType]] = None,
symbol: Optional[str] = None,
) -> SwcInternalBehavior:
"""创建 SWC 内部行为的工厂函数"""
return SwcInternalBehavior(
name=name,
runnable_entities=runnable_entities or [],
events=events or [],
symbol=symbol,
)
+43
View File
@@ -0,0 +1,43 @@
"""
单位数据类型模块
"""
from dataclasses import dataclass, field
from typing import Optional
from xml.dom.minidom import Document
from ..core.base import Base, create_uuid, create_text_element
from ..core.constants import UNIT, SHORT_NAME, FACTOR_SI_TO_UNIT, OFFSET_SI_TO_UNIT
@dataclass
class Unit(Base):
"""数据单位"""
display: Optional[str] = ''
factor: int = 1
offset: int = 0
def to_arxml(self, doc: Document) -> Document:
"""转换为 ARXML 元素"""
element = doc.createElement(UNIT)
element.setAttribute("UUID", create_uuid())
element.appendChild(create_text_element(doc, SHORT_NAME, self.name))
element.appendChild(create_text_element(doc, FACTOR_SI_TO_UNIT, str(self.factor)))
element.appendChild(create_text_element(doc, OFFSET_SI_TO_UNIT, str(self.offset)))
if self.display:
element.appendChild(create_text_element(doc, "DISPLAY", self.display))
return element
def create_unit(
name: str,
display: Optional[str] = None,
factor: int = 1,
offset: int = 0,
) -> Unit:
"""创建单位的工厂函数"""
return Unit(
name=name,
display=display or '',
factor=factor,
offset=offset,
)
+18
View File
@@ -0,0 +1,18 @@
"""
utils 模块 - ARXML 工具函数
"""
from .arxml_writer import (
create_arxml_document,
write_arxml,
write_arxml_pretty,
get_ar_packages_element,
add_package_to_document,
)
__all__ = [
"create_arxml_document",
"write_arxml",
"write_arxml_pretty",
"get_ar_packages_element",
"add_package_to_document",
]
+62
View File
@@ -0,0 +1,62 @@
"""
ARXML 文件写入工具模块
"""
from xml.dom.minidom import Document
from xml.dom.minidom import Element
from typing import Optional
from ..core.constants import AUTOSAR, AR_PACKAGES
def create_arxml_document() -> Document:
"""创建 ARXML 文档"""
doc = Document()
autosar = doc.createElement(AUTOSAR)
autosar.setAttribute("xmlns", "http://autosar.org/schema/r4.4")
autosar.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
autosar.setAttribute("xsi:schemaLocation", "http://autosar.org/schema/r4.4 AUTOSAR_4-4.xsd")
ar_packages = doc.createElement(AR_PACKAGES)
autosar.appendChild(ar_packages)
doc.appendChild(autosar)
return doc
def write_arxml(doc: Document, filepath: str, encoding: str = 'utf-8') -> None:
"""将 ARXML Document 写入文件
Args:
doc: ARXML Document 对象
filepath: 输出文件路径
encoding: 文件编码(默认 utf-8
"""
with open(filepath, 'w', encoding=encoding) as f:
xml_string = doc.toprettyxml(indent=' ', encoding=encoding)
f.write(xml_string.decode(encoding))
def write_arxml_pretty(doc: Document, filepath: str, encoding: str = 'utf-8') -> None:
"""将 ARXML Document 写入文件(格式化输出)
Args:
doc: ARXML Document 对象
filepath: 输出文件路径
encoding: 文件编码(默认 utf-8
"""
with open(filepath, 'w', encoding=encoding) as f:
f.write(doc.toprettyxml(indent=' '))
def get_ar_packages_element(doc: Document) -> Optional[Element]:
"""获取 AR-PACKAGES 元素"""
if doc.documentElement and doc.documentElement.tagName == AUTOSAR:
packages = doc.documentElement.getElementsByTagName(AR_PACKAGES)
if packages:
return packages[0]
return None
def add_package_to_document(doc: Document, package_element: Element) -> None:
"""添加 Package 元素到文档"""
packages = get_ar_packages_element(doc)
if packages is not None:
packages.appendChild(package_element)
+1
View File
@@ -0,0 +1 @@
"""测试包初始化"""
+82
View File
@@ -0,0 +1,82 @@
"""
核心模块测试
"""
import pytest
from src.core.base import Base, create_uuid, create_text_element
from src.core.enums import Category, Encoding, CalibrationAccess
class TestBase:
"""Base 基类测试"""
def test_base_creation(self):
"""测试基本创建"""
base = Base(name="TestElement")
assert base.name == "TestElement"
assert base.id is None
assert base.parent is None
assert base.description is None
def test_base_with_parent(self):
"""测试带父元素的创建"""
parent = Base(name="Parent")
child = Base(name="Child", parent=parent)
assert child.parent == parent
assert child.parent_id == parent.id
def test_package_path(self):
"""测试包路径计算"""
parent = Base(name="Parent")
child = Base(name="Child", parent=parent)
assert child.package_path == "/Parent/Child"
def test_package_path_deep(self):
"""测试深层包路径"""
level1 = Base(name="Level1")
level2 = Base(name="Level2", parent=level1)
level3 = Base(name="Level3", parent=level2)
level4 = Base(name="Level4", parent=level3)
assert level4.package_path == "/Level1/Level2/Level3/Level4"
class TestUtilityFunctions:
"""工具函数测试"""
def test_create_uuid(self):
"""测试 UUID 生成"""
uuid1 = create_uuid()
uuid2 = create_uuid()
assert uuid1 != uuid2
assert len(uuid1) == 36
def test_create_text_element(self):
"""测试文本元素创建"""
import xml.dom.minidom as Dom
doc = Dom.Document()
element = create_text_element(doc, "TEST_TAG", "test_value")
assert element.tagName == "TEST_TAG"
assert element.firstChild.nodeValue == "test_value"
class TestEnums:
"""枚举类型测试"""
def test_category_enum(self):
"""测试 Category 枚举"""
assert Category.FIXED_LENGTH is not None
assert Category.VALUE is not None
assert Category.STRUCTURE is not None
assert Category.ARRAY is not None
def test_calibration_access_enum(self):
"""测试 CalibrationAccess 枚举"""
assert CalibrationAccess.READ_ONLY is not None
assert CalibrationAccess.READ_WRITE is not None
assert CalibrationAccess.NOT_ACCESSIBLE is not None
assert CalibrationAccess.NOT_SPECIFIED is not None
if __name__ == "__main__":
pytest.main([__file__, "-v"])
+136
View File
@@ -0,0 +1,136 @@
"""
集成测试 - 完整 ARXML 文件生成
"""
import pytest
from xml.dom.minidom import Document
from src import (
create_base_type,
create_unit,
create_data_constraint,
create_compu_method,
create_linear,
create_boolean_type,
create_value_type,
create_structure_type,
create_impl_value_type,
create_sender_receiver_interface,
SenderReceiverInterface,
ApplicationStructureDataType,
Category,
CalibrationAccess,
)
class TestARXMLGeneration:
"""ARXML 生成测试"""
def test_full_type_chain(self):
"""测试完整的类型链(应用类型 -> 实现类型 -> 基础类型)"""
base_type = create_base_type("UInt8", size=8)
assert base_type.name == "UInt8"
impl_type = create_impl_value_type("ImplUInt8", base_type=base_type)
assert impl_type.name == "ImplUInt8"
assert impl_type.base_type == base_type
app_type = create_value_type("AppUInt8")
assert app_type.name == "AppUInt8"
doc = Document()
base_element = base_type.to_arxml(doc)
assert base_element.tagName == "SW-BASE-TYPE"
impl_element = impl_type.to_arxml(doc)
assert impl_element.tagName == "IMPLEMENTATION-DATA-TYPE"
app_element = app_type.to_arxml(doc)
assert app_element.tagName == "APPLICATION-PRIMITIVE-DATA-TYPE"
def test_unit_with_compu_method(self):
"""测试单位与计算方法关联"""
unit = create_unit("kmh", display="km/h")
linear = create_linear(factor=0.01, offset=0)
compu = create_compu_method("SpeedConversion", unit=unit, linear=linear)
assert compu.unit == unit
assert compu.linear == linear
def test_complex_structure(self):
"""测试复杂结构体"""
member1 = ApplicationStructureDataType.StructureElement(name="temperature")
member2 = ApplicationStructureDataType.StructureElement(name="humidity")
struct = create_structure_type("EnvironmentData", elements=[member1, member2])
assert len(struct.structure_elements) == 2
doc = Document()
element = struct.to_arxml(doc)
assert element.tagName == "APPLICATION-RECORD-DATA-TYPE"
def test_interface_creation(self):
"""测试接口创建"""
data_element = SenderReceiverInterface.DataElement(name="SpeedData")
interface = create_sender_receiver_interface(
"SpeedInterface",
data_element=data_element,
is_service=False
)
assert interface.name == "SpeedInterface"
assert interface.data_element == data_element
doc = Document()
element = interface.to_arxml(doc)
assert element.tagName == "SENDER-RECEIVER-INTERFACE"
def test_data_constraint_chain(self):
"""测试数据约束链"""
unit = create_unit("percent", display="%")
constraint = create_data_constraint(
"PercentageRange",
lower=0,
upper=100,
unit=unit
)
assert constraint.unit == unit
assert constraint.lower == 0
assert constraint.upper == 100
doc = Document()
element = constraint.to_arxml(doc)
assert element.tagName == "DATA-CONSTR"
def test_package_creation(self):
"""测试包创建"""
from src import create_package, create_base_type
base_type = create_base_type("TestType")
pkg = create_package("TestPackage", elements=[base_type])
assert pkg.name == "TestPackage"
assert len(pkg.elements) == 1
assert pkg.get_element("TestType") == base_type
def test_package_to_arxml(self):
"""测试包 ARXML 转换"""
from src import create_package, create_base_type
base_type = create_base_type("PackageType")
pkg = create_package("MyPackage", elements=[base_type])
doc = Document()
element = pkg.to_arxml(doc)
assert element.tagName == "AR-PACKAGE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "MyPackage"
elements = element.getElementsByTagName("ELEMENTS")
assert len(elements) == 1
if __name__ == "__main__":
pytest.main([__file__, "-v"])
+294
View File
@@ -0,0 +1,294 @@
"""
SWC 组件和内部行为测试
"""
import pytest
from xml.dom.minidom import Document
from src import (
ApplicationSwComponentType,
RPortPrototype,
PPortPrototype,
PRPortPrototype,
SenderReceiverInterface,
create_sender_receiver_interface,
create_runnable_entity,
create_timing_event,
create_init_event,
create_operation_invoked_event,
create_data_received_event,
create_swc_internal_behavior,
SwcInternalBehavior,
VariableAccess,
)
class TestRunnableEntity:
"""RunnableEntity 测试"""
def test_create_runnable_entity(self):
"""测试创建 Runnable 实体"""
runnable = create_runnable_entity(
name="Runnable_Init",
minimum_start_interval=10,
can_be_invoked_concurrently=False,
symbol="Runnable_Init_Function"
)
assert runnable.name == "Runnable_Init"
assert runnable.minimum_start_interval == 10
assert runnable.can_be_invoked_concurrently is False
assert runnable.symbol == "Runnable_Init_Function"
def test_runnable_entity_add_data_access(self):
"""测试 Runnable 添加数据访问"""
runnable = create_runnable_entity(name="TestRunnable")
access = VariableAccess(name="DataAccess", port_prototype_ref="Port1")
runnable.add_variable_access(access)
assert len(runnable.variable_accesses) == 1
def test_runnable_entity_to_arxml(self):
"""测试 Runnable 实体 ARXML 转换"""
runnable = create_runnable_entity(
name="TestRunnable",
symbol="TestRunnable_Func"
)
doc = Document()
element = runnable.to_arxml(doc)
assert element.tagName == "RUNNABLE-ENTITY"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "TestRunnable"
class TestEvents:
"""事件测试"""
def test_create_timing_event(self):
"""测试创建定时事件"""
event = create_timing_event("TimingEvent_10ms", period=0.01)
assert event.name == "TimingEvent_10ms"
assert event.period == 0.01
def test_timing_event_to_arxml(self):
"""测试定时事件 ARXML 转换"""
event = create_timing_event("PeriodicTask", period=0.05)
doc = Document()
element = event.to_arxml(doc)
assert element.tagName == "TIMING-EVENT"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "PeriodicTask"
def test_create_init_event(self):
"""测试创建初始化事件"""
event = create_init_event("InitEvent")
assert event.name == "InitEvent"
def test_init_event_to_arxml(self):
"""测试初始化事件 ARXML 转换"""
event = create_init_event("InitEvent")
doc = Document()
element = event.to_arxml(doc)
assert element.tagName == "INIT-EVENT"
assert element.hasAttribute("UUID")
def test_create_operation_invoked_event(self):
"""测试创建操作调用事件"""
event = create_operation_invoked_event(
"OpInvokeEvent",
operation_ref="/Package/Interface/Operation"
)
assert event.name == "OpInvokeEvent"
assert event.operation_ref == "/Package/Interface/Operation"
def test_operation_invoked_event_to_arxml(self):
"""测试操作调用事件 ARXML 转换"""
event = create_operation_invoked_event("OpInvokeEvent")
doc = Document()
element = event.to_arxml(doc)
assert element.tagName == "OPERATION-INVOKED-EVENT"
assert element.hasAttribute("UUID")
def test_create_data_received_event(self):
"""测试创建数据接收事件"""
event = create_data_received_event(
"DataReceived",
data_element_ref="/Package/Interface/Port",
period=0.02
)
assert event.name == "DataReceived"
assert event.data_element_ref == "/Package/Interface/Port"
assert event.period == 0.02
def test_data_received_event_to_arxml(self):
"""测试数据接收事件 ARXML 转换"""
event = create_data_received_event("DataReceived", period=0.01)
doc = Document()
element = event.to_arxml(doc)
assert element.tagName == "DATA-RECEIVED-EVENT"
assert element.hasAttribute("UUID")
class TestSwcInternalBehavior:
"""SWC 内部行为测试"""
def test_create_swc_internal_behavior(self):
"""测试创建 SWC 内部行为"""
runnable = create_runnable_entity(name="MainRunnable")
timing = create_timing_event("MainTiming", period=0.01)
behavior = create_swc_internal_behavior(
name="ComponentBehavior",
runnable_entities=[runnable],
events=[timing],
symbol="Component_Symbol"
)
assert behavior.name == "ComponentBehavior"
assert len(behavior.runnable_entities) == 1
assert len(behavior.events) == 1
assert behavior.symbol == "Component_Symbol"
def test_swc_internal_behavior_add_runnable(self):
"""测试 SWC 内部行为添加 Runnable"""
behavior = create_swc_internal_behavior(name="Behavior")
runnable = create_runnable_entity(name="NewRunnable")
behavior.add_runnable(runnable)
assert behavior.get_runnable("NewRunnable") == runnable
def test_swc_internal_behavior_add_event(self):
"""测试 SWC 内部行为添加事件"""
behavior = create_swc_internal_behavior(name="Behavior")
event = create_timing_event("NewTiming", period=0.02)
behavior.add_event(event)
assert behavior.get_event("NewTiming") == event
def test_swc_internal_behavior_to_arxml(self):
"""测试 SWC 内部行为 ARXML 转换"""
runnable = create_runnable_entity(name="MainRunnable", symbol="MainRunnable_Func")
timing = create_timing_event("Periodic", period=0.01)
behavior = create_swc_internal_behavior(
name="ComponentBehavior",
runnable_entities=[runnable],
events=[timing]
)
doc = Document()
element = behavior.to_arxml(doc)
assert element.tagName == "SWC-INTERNAL-BEHAVIOR"
assert element.hasAttribute("UUID")
class TestSwComponent:
"""软件组件测试"""
def test_create_application_swc(self):
"""测试创建应用组件"""
swc = ApplicationSwComponentType(name="TestComponent")
assert swc.name == "TestComponent"
assert swc.atomic_type.value == "Application"
def test_application_swc_add_port(self):
"""测试应用组件添加端口"""
swc = ApplicationSwComponentType(name="TestComponent")
data_element = SenderReceiverInterface.DataElement(name="TestData")
interface = create_sender_receiver_interface("TestInterface", data_element=data_element)
port = PPortPrototype(name="TestPort", interface=interface)
swc.add_port(port)
assert swc.get_port("TestPort") == port
def test_application_swc_to_arxml(self):
"""测试应用组件 ARXML 转换"""
swc = ApplicationSwComponentType(name="TestComponent")
doc = Document()
element = swc.to_arxml(doc)
assert element.tagName == "APPLICATION-SW-COMPONENT-TYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "TestComponent"
def test_application_swc_with_ports_to_arxml(self):
"""测试带端口的应用组件 ARXML 转换"""
swc = ApplicationSwComponentType(name="ComponentWithPorts")
data_element = SenderReceiverInterface.DataElement(name="StatusData")
interface = create_sender_receiver_interface("StatusInterface", data_element=data_element)
port = PPortPrototype(name="StatusPort", interface=interface)
swc.add_port(port)
doc = Document()
element = swc.to_arxml(doc)
assert element.tagName == "APPLICATION-SW-COMPONENT-TYPE"
ports = element.getElementsByTagName("PORTS")
assert len(ports) == 1
class TestPortPrototypes:
"""端口原型测试"""
def test_r_port_prototype_to_arxml(self):
"""测试 R-Port ARXML 转换"""
data_element = SenderReceiverInterface.DataElement(name="RxData")
interface = create_sender_receiver_interface("RxInterface", data_element=data_element)
port = RPortPrototype(name="RPort1", interface=interface)
doc = Document()
element = port.to_arxml(doc)
assert element.tagName == "R-PORT-PROTOTYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "RPort1"
def test_p_port_prototype_to_arxml(self):
"""测试 P-Port ARXML 转换"""
data_element = SenderReceiverInterface.DataElement(name="TxData")
interface = create_sender_receiver_interface("TxInterface", data_element=data_element)
port = PPortPrototype(name="PPort1", interface=interface)
doc = Document()
element = port.to_arxml(doc)
assert element.tagName == "P-PORT-PROTOTYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "PPort1"
def test_pr_port_prototype_to_arxml(self):
"""测试 PR-Port ARXML 转换"""
data_element = SenderReceiverInterface.DataElement(name="BidirectionalData")
interface = create_sender_receiver_interface("BiInterface", data_element=data_element)
port = PRPortPrototype(name="PRPort1", interface=interface)
doc = Document()
element = port.to_arxml(doc)
assert element.tagName == "P-PORT-PROTOTYPE"
assert element.hasAttribute("UUID")
if __name__ == "__main__":
pytest.main([__file__, "-v"])
+423
View File
@@ -0,0 +1,423 @@
"""
数据类型测试
"""
import pytest
from xml.dom.minidom import Document
from src import (
BaseType,
create_base_type,
Unit,
create_unit,
Category,
Encoding,
)
from src.core.base import create_uuid, create_text_element
class TestBaseType:
"""BaseType 测试"""
def test_create_base_type(self):
"""测试创建基础类型"""
base_type = create_base_type("UInt8", size=8)
assert base_type.name == "UInt8"
assert base_type.size == 8
assert base_type.category == Category.FIXED_LENGTH
def test_base_type_encoding(self):
"""测试编码属性"""
base_type = create_base_type(
"SInt8",
encoding=Encoding.TWO_COMPONENT
)
assert base_type.encoding_value == "2C"
def test_base_type_to_arxml(self):
"""测试 ARXML 转换"""
base_type = create_base_type("UInt16", size=16)
doc = Document()
element = base_type.to_arxml(doc)
assert element.tagName == "SW-BASE-TYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "UInt16"
class TestUnit:
"""Unit 测试"""
def test_create_unit(self):
"""测试创建单位"""
unit = create_unit("kmh", display="km/h", factor=1, offset=0)
assert unit.name == "kmh"
assert unit.display == "km/h"
assert unit.factor == 1
assert unit.offset == 0
def test_unit_to_arxml(self):
"""测试单位 ARXML 转换"""
unit = create_unit("m/s", display="meters per second")
doc = Document()
element = unit.to_arxml(doc)
assert element.tagName == "UNIT"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "m/s"
class TestDataConstraint:
"""DataConstraint 测试"""
def test_create_data_constraint(self):
"""测试创建数据约束"""
from src import create_data_constraint
constraint = create_data_constraint(
"SpeedConstraint",
lower=0,
upper=250
)
assert constraint.name == "SpeedConstraint"
assert constraint.lower == 0
assert constraint.upper == 250
def test_data_constraint_to_arxml(self):
"""测试数据约束 ARXML 转换"""
from src import create_data_constraint
constraint = create_data_constraint(
"RangeConstraint",
lower=0,
upper=100
)
doc = Document()
element = constraint.to_arxml(doc)
assert element.tagName == "DATA-CONSTR"
assert element.hasAttribute("UUID")
class TestCompuMethod:
"""CompuMethod 测试"""
def test_create_compu_method(self):
"""测试创建计算方法"""
from src import create_compu_method, create_linear
linear = create_linear(factor=0.1, offset=10)
compu = create_compu_method(
"LinearConversion",
linear=linear
)
assert compu.name == "LinearConversion"
assert compu.linear == linear
assert compu.category == Category.IDENTICAL
def test_compu_method_with_text_table(self):
"""测试带文本表的计算方法"""
from src import create_compu_method, create_text_table
text_table = create_text_table("OnOff", "ON", 0, 1)
compu = create_compu_method(
"OnOffTable",
text_tables=[text_table]
)
assert len(compu.text_tables) == 1
assert compu.get_text_table("ON") == text_table
def test_compu_method_to_arxml(self):
"""测试计算方法 ARXML 转换"""
from src import create_compu_method
compu = create_compu_method("TestMethod")
doc = Document()
element = compu.to_arxml(doc)
assert element.tagName == "COMPU-METHOD"
assert element.hasAttribute("UUID")
class TestApplicationTypes:
"""应用数据类型测试"""
def test_create_boolean_type(self):
"""测试创建布尔类型"""
from src import create_boolean_type
bool_type = create_boolean_type("BooleanSignal")
assert bool_type.name == "BooleanSignal"
assert bool_type.category == Category.BOOLEAN
def test_create_value_type(self):
"""测试创建值类型"""
from src import create_value_type
value_type = create_value_type("SpeedValue")
assert value_type.name == "SpeedValue"
assert value_type.category == Category.VALUE
def test_create_structure_type(self):
"""测试创建结构体类型"""
from src import create_structure_type, ApplicationStructureDataType
element = ApplicationStructureDataType.StructureElement(name="member1")
struct_type = create_structure_type("MyStruct", elements=[element])
assert struct_type.name == "MyStruct"
assert len(struct_type.structure_elements) == 1
assert struct_type.get_element("member1") == element
class TestImplementationTypes:
"""实现数据类型测试"""
def test_create_impl_value_type(self):
"""测试创建实现值类型"""
from src import create_impl_value_type, create_base_type
base = create_base_type("UInt8")
impl_type = create_impl_value_type("ImplUInt8", base_type=base)
assert impl_type.name == "ImplUInt8"
assert impl_type.base_type == base
assert impl_type.category == Category.VALUE
def test_create_impl_structure_type(self):
"""测试创建实现结构体类型"""
from src import create_impl_structure_type, ImplementationStructureDataType
element = ImplementationStructureDataType.StructureElement(name="field1")
struct = create_impl_structure_type("ImplStruct", elements=[element])
assert struct.name == "ImplStruct"
assert len(struct.structure_elements) == 1
def test_impl_value_type_to_arxml(self):
"""测试实现值类型 ARXML 转换"""
from src import create_impl_value_type, create_base_type
base = create_base_type("UInt8")
impl_type = create_impl_value_type("ImplUInt8", base_type=base)
doc = Document()
element = impl_type.to_arxml(doc)
assert element.tagName == "IMPLEMENTATION-DATA-TYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "ImplUInt8"
def test_impl_structure_type_to_arxml(self):
"""测试实现结构体类型 ARXML 转换"""
from src import create_impl_structure_type, ImplementationStructureDataType
element = ImplementationStructureDataType.StructureElement(name="field1")
struct = create_impl_structure_type("ImplStruct", elements=[element])
doc = Document()
element = struct.to_arxml(doc)
assert element.tagName == "IMPLEMENTATION-DATA-TYPE"
assert element.hasAttribute("UUID")
class TestLinear:
"""Linear 转换测试"""
def test_linear_to_arxml(self):
"""测试线性转换 ARXML 转换"""
from src import create_linear
linear = create_linear(factor=0.1, offset=10)
doc = Document()
element = linear.to_arxml(doc)
assert element.tagName == "COMPU-SCALE"
assert element.hasChildNodes()
class TestTextTable:
"""TextTable 文本表测试"""
def test_create_text_table(self):
"""测试创建文本表"""
from src import create_text_table
text_table = create_text_table("OnOff", "ON", 0, 1)
assert text_table.name == "OnOff"
assert text_table.vt == "ON"
assert text_table.lower == 0
assert text_table.upper == 1
def test_text_table_to_arxml(self):
"""测试文本表 ARXML 转换"""
from src import create_text_table
text_table = create_text_table("Status", "ACTIVE", 1, 2)
doc = Document()
element = text_table.to_arxml(doc)
assert element.tagName == "COMPU-SCALE"
assert element.hasChildNodes()
vt_elem = element.getElementsByTagName("VT")
assert len(vt_elem) > 0
class TestInterfaces:
"""接口测试"""
def test_client_server_interface_creation(self):
"""测试创建客户端-服务端接口"""
from src import ClientServerInterface
cs_interface = ClientServerInterface(name="TestService")
assert cs_interface.name == "TestService"
assert cs_interface.is_service is False
operation = ClientServerInterface.Operation(name="StartOperation")
cs_interface.add_operation(operation)
assert cs_interface.get_operation("StartOperation") == operation
def test_client_server_interface_to_arxml(self):
"""测试客户端-服务端接口 ARXML 转换"""
from src import ClientServerInterface
cs_interface = ClientServerInterface(name="TestService")
operation = ClientServerInterface.Operation(name="StartOperation")
cs_interface.add_operation(operation)
doc = Document()
element = cs_interface.to_arxml(doc)
assert element.tagName == "CLIENT-SERVER-INTERFACE"
assert element.hasAttribute("UUID")
def test_client_server_operation_to_arxml(self):
"""测试操作方法 ARXML 转换"""
from src import ClientServerInterface
operation = ClientServerInterface.Operation(name="TestOp", is_server=True)
doc = Document()
element = operation.to_arxml(doc)
assert element.tagName == "CLIENT-SERVER-OPERATION"
assert element.hasAttribute("UUID")
class TestDataMapping:
"""数据类型映射测试"""
def test_data_type_mapping_creation(self):
"""测试创建数据类型映射"""
from src import create_data_type_mapping
mapping = create_data_type_mapping("TestMapping")
assert mapping.name == "TestMapping"
def test_data_type_mapping_to_arxml(self):
"""测试数据类型映射 ARXML 转换"""
from src import create_data_type_mapping
mapping = create_data_type_mapping("TestMapping")
doc = Document()
element = mapping.to_arxml(doc)
assert element.tagName == "DATA-TYPE-MAP"
def test_data_type_mapping_set_creation(self):
"""测试创建数据类型映射集"""
from src import create_data_type_mapping_set, create_data_type_mapping
mapping1 = create_data_type_mapping("Mapping1")
mapping_set = create_data_type_mapping_set("TestSet", mappings=[mapping1])
assert mapping_set.name == "TestSet"
assert len(mapping_set.data_type_mappings) == 1
assert mapping_set.get_mapping("Mapping1") == mapping1
def test_data_type_mapping_set_to_arxml(self):
"""测试数据类型映射集 ARXML 转换"""
from src import create_data_type_mapping_set
mapping_set = create_data_type_mapping_set("TestSet")
doc = Document()
element = mapping_set.to_arxml(doc)
assert element.tagName == "DATA-TYPE-MAPPING-SET"
assert element.hasAttribute("UUID")
class TestApplicationTypesToArxml:
"""应用数据类型 ARXML 测试"""
def test_value_type_to_arxml(self):
"""测试应用值类型 ARXML 转换"""
from src import create_value_type
value_type = create_value_type("SpeedValue")
doc = Document()
element = value_type.to_arxml(doc)
assert element.tagName == "APPLICATION-PRIMITIVE-DATA-TYPE"
assert element.hasAttribute("UUID")
short_name = element.getElementsByTagName("SHORT-NAME")[0]
assert short_name.firstChild.nodeValue == "SpeedValue"
def test_boolean_type_to_arxml(self):
"""测试布尔类型 ARXML 转换"""
from src import create_boolean_type
bool_type = create_boolean_type("IsActive")
doc = Document()
element = bool_type.to_arxml(doc)
assert element.tagName == "APPLICATION-PRIMITIVE-DATA-TYPE"
assert element.hasAttribute("UUID")
def test_structure_type_to_arxml(self):
"""测试应用结构体类型 ARXML 转换"""
from src import create_structure_type, ApplicationStructureDataType
element = ApplicationStructureDataType.StructureElement(name="member1")
struct = create_structure_type("MyStruct", elements=[element])
doc = Document()
arxml_element = struct.to_arxml(doc)
assert arxml_element.tagName == "APPLICATION-RECORD-DATA-TYPE"
assert arxml_element.hasAttribute("UUID")
def test_array_type_to_arxml(self):
"""测试应用数组类型 ARXML 转换"""
from src import create_array_type, create_value_type, ApplicationArrayDataType, Semantic
element_type = create_value_type("ArrayElement")
array_element = ApplicationArrayDataType.ArrayElement(
name="element",
data_type=element_type,
array_size_semantics=Semantic.FIXED,
length=10
)
array_type = create_array_type("MyArray", element=array_element)
doc = Document()
arxml_element = array_type.to_arxml(doc)
assert arxml_element.tagName == "APPLICATION-ARRAY-DATA-TYPE"
assert arxml_element.hasAttribute("UUID")
if __name__ == "__main__":
pytest.main([__file__, "-v"])