Skip to content

Commit

Permalink
add support for internalconstr
Browse files Browse the repository at this point in the history
  • Loading branch information
willzhang05 committed Dec 1, 2023
1 parent 262f6c8 commit 52892db
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 7 deletions.
10 changes: 10 additions & 0 deletions examples/somersaultecu.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"soberness_check":
DataObjectProperty(
Expand All @@ -474,6 +475,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"dizzyness_level":
DataObjectProperty(
Expand All @@ -487,6 +489,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"happiness_level":
DataObjectProperty(
Expand All @@ -500,6 +503,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"duration":
DataObjectProperty(
Expand All @@ -513,6 +517,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=OdxLinkRef.from_id(somersault_units["second"].odx_id),
sdgs=[],
internal_constr=None,
),
"temperature":
DataObjectProperty(
Expand All @@ -526,6 +531,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=OdxLinkRef.from_id(somersault_units["celsius"].odx_id),
sdgs=[],
internal_constr=None,
),
"error_code":
DataObjectProperty(
Expand All @@ -539,6 +545,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"boolean":
DataObjectProperty(
Expand All @@ -553,6 +560,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["boolean"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"uint8":
DataObjectProperty(
Expand All @@ -566,6 +574,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"float":
DataObjectProperty(
Expand All @@ -579,6 +588,7 @@ class SomersaultSID(IntEnum):
compu_method=somersault_compumethods["float_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
}

Expand Down
9 changes: 8 additions & 1 deletion odxtools/dataobjectproperty.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .dopbase import DopBase
from .encodestate import EncodeState
from .exceptions import DecodeError, EncodeError, odxassert, odxrequire
from .internalconstr import InternalConstr
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
from .odxtypes import AtomicOdxType, ParameterValue
from .physicaltype import PhysicalType
Expand Down Expand Up @@ -42,7 +43,7 @@ class DataObjectProperty(DopBase):
unit_ref: Optional[OdxLinkRef]

# TODO: physical_const: Optional[InternalConstr]
# TODO: internal_const: Optional[InternalConstr]
internal_constr: Optional[InternalConstr]

@staticmethod
def from_et(et_element: ElementTree.Element,
Expand All @@ -63,11 +64,17 @@ def from_et(et_element: ElementTree.Element,
)
unit_ref = OdxLinkRef.from_et(et_element.find("UNIT-REF"), doc_frags)

internal_constr = None
if (internal_constr_elem := et_element.find("INTERNAL-CONSTR")) is not None:
internal_constr = InternalConstr.from_et(
internal_constr_elem, internal_type=diag_coded_type.base_data_type)

return DataObjectProperty(
diag_coded_type=diag_coded_type,
physical_type=physical_type,
compu_method=compu_method,
unit_ref=unit_ref,
internal_constr=internal_constr,
**kwargs)

def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
Expand Down
79 changes: 79 additions & 0 deletions odxtools/internalconstr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from enum import Enum
from typing import List, Optional
from xml.etree import ElementTree

from .compumethods.limit import Limit
from .exceptions import odxraise, odxrequire
from .odxtypes import DataType
from .utils import create_description_from_et


class Validity(Enum):
VALID = "VALID"
NOT_VALID = "NOT-VALID"
NOT_DEFINED = "NOT-DEFINED"
NOT_AVAILABLE = "NOT-AVAILABLE"


@dataclass
class ScaleConstr:
"""This class represents a SCALE-CONSTR.
"""

short_label: Optional[str]
description: Optional[str]
lower_limit: Optional[Limit]
upper_limit: Optional[Limit]
validity: Validity

@staticmethod
def from_et(et_element: ElementTree.Element, internal_type: DataType) -> "ScaleConstr":
short_label = et_element.findtext("SHORT-LABEL")
description = create_description_from_et(et_element.find("DESC"))

lower_limit = Limit.from_et(et_element.find("LOWER-LIMIT"), internal_type=internal_type)
upper_limit = Limit.from_et(et_element.find("UPPER-LIMIT"), internal_type=internal_type)

validity_str = odxrequire(et_element.get("VALIDITY"))
try:
validity = Validity(validity_str)
except ValueError:
odxraise(f"Encountered unknown Validity '{validity_str}'")

return ScaleConstr(
short_label=short_label,
description=description,
lower_limit=lower_limit,
upper_limit=upper_limit,
validity=validity)


@dataclass
class InternalConstr:
"""This class represents a INTERNAL-CONSTR.
"""

lower_limit: Optional[Limit]
upper_limit: Optional[Limit]
scale_constrs: List[ScaleConstr]

@staticmethod
def from_et(et_element: ElementTree.Element, internal_type: DataType) -> "InternalConstr":

lower_limit = None
if lower_limit_elem := et_element.find("LOWER-LIMIT"):
lower_limit = Limit.from_et(lower_limit_elem, internal_type=internal_type)

upper_limit = None
if upper_limit_elem := et_element.find("UPPER-LIMIT"):
upper_limit = Limit.from_et(upper_limit_elem, internal_type=internal_type)

scale_constrs = [
ScaleConstr.from_et(sc_el, internal_type)
for sc_el in et_element.iterfind("SCALE-CONSTRS/SCALE-CONSTR")
]

return InternalConstr(
lower_limit=lower_limit, upper_limit=upper_limit, scale_constrs=scale_constrs)
46 changes: 40 additions & 6 deletions odxtools/templates/macros/printDOP.xml.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
{%- macro printPhysicalType(physical_type) %}
{%- if physical_type.display_radix is not none %}
<PHYSICAL-TYPE BASE-DATA-TYPE="{{physical_type.base_data_type.value}}" DISPLAY-RADIX="{{physical_type.display_radix.name}}" />
{%- elif physical_type.precision is not none %}
{%- elif physical_type.precision is not none %}
<PHYSICAL-TYPE BASE-DATA-TYPE="{{physical_type.base_data_type.value}}">
<PRECISION>{{physical_type.precision}}</PRECISION>
</PHYSICAL-TYPE>
Expand All @@ -44,12 +44,43 @@
{%- endmacro -%}

{%- macro printLimitValue(lv) -%}
{%- if hasattr(lv, 'hex') %}
{%- if hasattr(lv, 'hex') -%}
{#- bytes or bytarray limit #}
{{lv.hex()}}
{%- else %}
{%- else -%}
{{lv}}
{%- endif %}
{%- endif -%}
{%- endmacro -%}

{%- macro printScaleConstr(sc) %}
<SCALE-CONSTR VALIDITY="{{sc.validity.value}}">
{%- if sc.short_label and sc.short_label.strip() %}
<SHORT-LABEL>{{sc.short_label|e}}</SHORT-LABEL>
{%- endif %}
{%- if sc.description and sc.description.strip() %}
<DESC>
{{sc.description}}
</DESC>
{%- endif %}
<LOWER-LIMIT>{{printLimitValue(sc.lower_limit.value)}}</LOWER-LIMIT>
<UPPER-LIMIT>{{printLimitValue(sc.upper_limit.value)}}</UPPER-LIMIT>
</SCALE-CONSTR>
{%- endmacro -%}

{%- macro printInternalConstr(ic) %}
<INTERNAL-CONSTR>
{%- if ic.lower_limit %}
<LOWER-LIMIT>{{printLimitValue(ic.lower_limit.value)}}</LOWER-LIMIT>
{%- endif %}
{%- if ic.upper_limit %}
<UPPER-LIMIT>{{printLimitValue(ic.upper_limit.value)}}</UPPER-LIMIT>
{%- endif %}
{%- for sc in ic.scale_constrs %}
<SCALE-CONSTRS>
{{- printScaleConstr(sc)|indent(4)}}
</SCALE-CONSTRS>
{%- endfor %}
</INTERNAL-CONSTR>
{%- endmacro -%}

{%- macro printCompuMethod(cm) -%}
Expand All @@ -69,10 +100,10 @@
</DESC>
{%- endif %}
{%- if cs.lower_limit is not none %}
<LOWER-LIMIT>{{printLimitValue(cs.lower_limit.value)}}</LOWER-LIMIT>
<LOWER-LIMIT>{{printLimitValue(cs.lower_limit.value)}}</LOWER-LIMIT>
{%- endif %}
{%- if cs.upper_limit is not none %}
<UPPER-LIMIT>{{printLimitValue(cs.upper_limit.value)}}</UPPER-LIMIT>
<UPPER-LIMIT>{{printLimitValue(cs.upper_limit.value)}}</UPPER-LIMIT>
{%- endif %}
{%- if cs.compu_inverse_value is not none %}
<COMPU-INVERSE-VALUE>
Expand Down Expand Up @@ -194,6 +225,9 @@
{%- if dop.unit_ref %}
<UNIT-REF ID-REF="{{ dop.unit_ref.ref_id }}" />
{%- endif %}
{%- if dop.internal_constr %}
{{- printInternalConstr(dop.internal_constr)|indent(1) }}
{%- endif %}
</DATA-OBJECT-PROP>
{%- endmacro %}

Expand Down
5 changes: 5 additions & 0 deletions tests/test_decoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ def test_decode_request_structure(self) -> None:
compu_method=compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)

req_param1 = CodedConstParameter(
Expand Down Expand Up @@ -731,6 +732,7 @@ def test_decode_request_end_of_pdu_field(self) -> None:
compu_method=compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)

req_param1 = CodedConstParameter(
Expand Down Expand Up @@ -940,6 +942,7 @@ def test_decode_request_linear_compu_method(self) -> None:
compu_method=compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)
req_param1 = CodedConstParameter(
short_name="SID",
Expand Down Expand Up @@ -1367,6 +1370,7 @@ def setUp(self) -> None:
internal_type=DataType.A_BYTEFIELD, physical_type=DataType.A_BYTEFIELD),
unit_ref=None,
sdgs=[],
internal_constr=None,
)
dop = self.dop_bytes_termination_end_of_pdu
odxlinks.update(dop._build_odxlinks())
Expand Down Expand Up @@ -1521,6 +1525,7 @@ def test_physical_constant_parameter(self) -> None:
),
unit_ref=None,
sdgs=[],
internal_constr=None,
)
odxlinks.update(dop._build_odxlinks())
req_param1 = CodedConstParameter(
Expand Down
4 changes: 4 additions & 0 deletions tests/test_diag_coded_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ def test_end_to_end(self) -> None:
compu_method=compumethods["bytes_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
}

Expand Down Expand Up @@ -459,6 +460,7 @@ def test_end_to_end(self) -> None:
compu_method=compumethods["multiply_with_8"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
"certificateClient":
DataObjectProperty(
Expand All @@ -473,6 +475,7 @@ def test_end_to_end(self) -> None:
compu_method=compumethods["uint_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
}

Expand Down Expand Up @@ -780,6 +783,7 @@ def test_end_to_end(self) -> None:
compu_method=compumethods["bytes_passthrough"],
unit_ref=None,
sdgs=[],
internal_constr=None,
),
}

Expand Down
2 changes: 2 additions & 0 deletions tests/test_diag_data_dictionary_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def test_initialization(self) -> None:
compu_method=ident_compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)

dop_2 = DataObjectProperty(
Expand All @@ -94,6 +95,7 @@ def test_initialization(self) -> None:
compu_method=ident_compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)

flip_quality_id = OdxLinkId("somersault.table.flip_quality", doc_frags)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def test_encode_linear(self) -> None:
compu_method=compu_method,
unit_ref=None,
sdgs=[],
internal_constr=None,
)
odxlinks.update({dop.odx_id: dop})
param1 = ValueParameter(
Expand Down Expand Up @@ -358,6 +359,7 @@ def test_bit_mask(self) -> None:
"sdgs": [],
"short_name": 'dop',
"unit_ref": None,
"internal_constr": None,
}
param_kwargs: Dict[str, Any] = {
"long_name": None,
Expand Down
Loading

0 comments on commit 52892db

Please sign in to comment.