Source code for uds.can.addressing.abstract_addressing_information

"""Abstract definition of Addressing Information handler."""

__all__ = ["AbstractCanAddressingInformation", "CANAddressingParams"]

from abc import ABC, abstractmethod
from typing import Any, Optional, TypedDict

from uds.addressing import AddressingType
from uds.addressing.abstract_addressing_information import AbstractAddressingInformation
from uds.can.addressing.addressing_format import CanAddressingFormat
from uds.utilities import RawBytesAlias


[docs] class CANAddressingParams(TypedDict, total=True): """:ref:`Addressing Information <knowledge-base-n-ai>` parameters collection for a single CAN Packet.""" addressing_format: CanAddressingFormat addressing_type: AddressingType can_id: int target_address: Optional[int] source_address: Optional[int] address_extension: Optional[int]
[docs] class AbstractCanAddressingInformation(AbstractAddressingInformation, ABC): """Abstract definition of storage for addressing related parameters for UDS entity operating on CAN bus."""
[docs] class InputAIParams(TypedDict, total=False): """:ref:`Addressing Information <knowledge-base-n-ai>` configuration parameters.""" can_id: int target_address: Optional[int] source_address: Optional[int] address_extension: Optional[int]
[docs] class CanIdAIParams(TypedDict, total=True): """ref:`Addressing Information <knowledge-base-n-ai>` parameters that are carried by CAN Identifier.""" addressing_type: Optional[AddressingType] target_address: Optional[int] source_address: Optional[int] priority: Optional[int]
[docs] class DataBytesAIParamsAlias(TypedDict, total=False): """Alias of :ref:`Addressing Information <knowledge-base-n-ai>` parameters encoded in data field.""" target_address: int address_extension: int
[docs] class DecodedAIParamsAlias(TypedDict, total=True): """Alias of :ref:`Addressing Information <knowledge-base-n-ai>` parameters encoded in CAN ID and data field.""" addressing_type: Optional[AddressingType] target_address: Optional[int] source_address: Optional[int] address_extension: Optional[int]
ADDRESSING_FORMAT: CanAddressingFormat """CAN Addressing Format used.""" AI_DATA_BYTES_NUMBER: int """Number of CAN Frame data bytes that are used to carry UDS Addressing Information.""" def __init__(self, rx_physical_params: InputAIParams, tx_physical_params: InputAIParams, rx_functional_params: InputAIParams, tx_functional_params: InputAIParams) -> None: """ Configure Addresses of UDS Entity (either a server or a client) for UDS over CAN communication. :param rx_physical_params: Addressing parameters for incoming physically addressed communication. :param tx_physical_params: Addressing parameters for outgoing physically addressed communication. :param rx_functional_params: Addressing parameters for incoming functionally addressed communication. :param tx_functional_params: Addressing parameters for outgoing functionally addressed communication. """ super().__init__(rx_physical_params=rx_physical_params, tx_physical_params=tx_physical_params, rx_functional_params=rx_functional_params, tx_functional_params=tx_functional_params)
[docs] @classmethod @abstractmethod def validate_addressing_params(cls, # type: ignore # pylint: disable=arguments-differ addressing_type: AddressingType, addressing_format: CanAddressingFormat, can_id: Optional[int] = None, target_address: Optional[int] = None, source_address: Optional[int] = None, address_extension: Optional[int] = None) -> CANAddressingParams: """ Validate Addressing Information parameters of a CAN packet. :param addressing_type: Addressing type to validate. :param addressing_format: CAN Addressing Format used. :param can_id: CAN Identifier value to validate. :param target_address: Target Address value to validate. :param source_address: Source Address value to validate. :param address_extension: Address Extension value to validate. :raise UnusedArgumentError: At least one provided parameter is not supported by Addressing format used. :raise InconsistencyError: Provided values are not consistent with each other (cannot be used together) or with the Addressing format used. :return: Normalized dictionary with the provided information. """
[docs] @staticmethod @abstractmethod def is_compatible_can_id(can_id: int, addressing_type: Optional[AddressingType]) -> bool: """ Check whether provided CAN ID is consistent with this CAN Addressing Format. :param can_id: Value of CAN ID to check. :param addressing_type: Addressing type for which consistency to be performed. Leave None to skip crosscheck between CAN Identifier and Addressing Type. :return: True if CAN ID value is compatible with this CAN Addressing Format, False otherwise. """
[docs] @staticmethod @abstractmethod def decode_can_id_ai_params(can_id: int) -> CanIdAIParams: """ Decode Addressing Information parameters from CAN Identifier. :param can_id: Value of a CAN Identifier. :return: Decoded Addressing Information parameters. """
[docs] @staticmethod @abstractmethod def decode_data_bytes_ai_params(ai_data_bytes: RawBytesAlias) -> DataBytesAIParamsAlias: """ Decode Addressing Information parameters from CAN data bytes. :param ai_data_bytes: Data bytes containing Addressing Information. :return: Decoded Addressing Information parameters. """
[docs] @classmethod def decode_frame_ai_params(cls, can_id: int, raw_frame_data: RawBytesAlias) -> DecodedAIParamsAlias: """ Decode Addressing Information parameters from a CAN Frame. :param can_id: CAN Identifier value of a CAN frame. :param raw_frame_data: Raw data bytes of a CAN frame. :return: Decoded Addressing Information parameters. """ can_ai_params = cls.decode_can_id_ai_params(can_id) data_ai_params = cls.decode_data_bytes_ai_params(raw_frame_data[:cls.AI_DATA_BYTES_NUMBER]) return cls.DecodedAIParamsAlias( addressing_type=can_ai_params["addressing_type"], target_address=data_ai_params.get("target_address", can_ai_params["target_address"]), source_address=can_ai_params["source_address"], address_extension=data_ai_params.get("address_extension", None) )
[docs] @classmethod @abstractmethod def encode_ai_data_bytes(cls, target_address: Optional[int] = None, address_extension: Optional[int] = None) -> bytearray: """ Generate data bytes that carry Addressing Information. :param target_address: Target Address value used. :param address_extension: Source Address value used. :return: Data bytes that carry Addressing Information in a CAN frame Data field. """
[docs] def is_input_packet(self, # type: ignore # pylint: disable=arguments-differ can_id: int, raw_frame_data: RawBytesAlias, **_: Any) -> Optional[AddressingType]: """ Check if a frame with provided attributes is an input packet for this UDS Entity. :param raw_frame_data: Raw data bytes carried by a CAN frame to check. :param can_id: CAN Identifier of a CAN frame to check. :return: Addressing Type used for transmission of this packet, None otherwise. """ try: decoded_frame_ai_params = self.decode_frame_ai_params(can_id=can_id, raw_frame_data=raw_frame_data) except ValueError: return None if (decoded_frame_ai_params["addressing_type"] in {None, AddressingType.PHYSICAL} and can_id == self.rx_physical_params["can_id"] and decoded_frame_ai_params["target_address"] == self.rx_physical_params["target_address"] and decoded_frame_ai_params["source_address"] == self.rx_physical_params["source_address"] and decoded_frame_ai_params["address_extension"] == self.rx_physical_params["address_extension"]): return AddressingType.PHYSICAL if (decoded_frame_ai_params["addressing_type"] in {None, AddressingType.FUNCTIONAL} and can_id == self.rx_functional_params["can_id"] and decoded_frame_ai_params["target_address"] == self.rx_functional_params["target_address"] and decoded_frame_ai_params["source_address"] == self.rx_functional_params["source_address"] and decoded_frame_ai_params["address_extension"] == self.rx_functional_params["address_extension"]): return AddressingType.FUNCTIONAL return None