Source code for uds.can.addressing.extended_addressing

"""Implementation of Extended CAN Addressing format."""

__all__ = ["ExtendedCanAddressingInformation"]

from typing import Optional

from uds.addressing import AddressingType
from uds.can.addressing.abstract_addressing_information import AbstractCanAddressingInformation, CANAddressingParams
from uds.can.addressing.addressing_format import CanAddressingFormat
from uds.can.frame import CanIdHandler
from uds.utilities import InconsistencyError, RawBytesAlias, UnusedArgumentError, validate_raw_byte, validate_raw_bytes


[docs] class ExtendedCanAddressingInformation(AbstractCanAddressingInformation): """Addressing Information of CAN Entity (either server or client) that uses Extended Addressing format.""" ADDRESSING_FORMAT = CanAddressingFormat.EXTENDED_ADDRESSING """CAN Addressing Format used.""" AI_DATA_BYTES_NUMBER = 1 """Number of CAN frame data bytes that are used to carry Addressing Information."""
[docs] def _validate_addressing_information(self) -> None: """ Validate Addressing Information parameters. :raise InconsistencyError: Provided values are not consistent with each other. """ rx_can_ids = {self.rx_physical_params["can_id"], self.rx_functional_params["can_id"]} tx_can_ids = {self.tx_physical_params["can_id"], self.tx_functional_params["can_id"]} if (self.rx_physical_params["can_id"] in tx_can_ids or self.tx_physical_params["can_id"] in rx_can_ids or self.rx_functional_params["can_id"] in tx_can_ids or self.tx_functional_params["can_id"] in rx_can_ids): raise InconsistencyError("CAN ID used for transmission cannot be used for receiving too.")
[docs] @classmethod def validate_addressing_params(cls, # type: ignore addressing_type: AddressingType, addressing_format: CanAddressingFormat = ADDRESSING_FORMAT, 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 that uses Extended Addressing format. :param addressing_type: Addressing type to validate. :param addressing_format: CAN Addressing Format to validate. :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 ValueError: Provided Addressing format cannot be handled by this class. :raise UnusedArgumentError: Provided parameter is not supported by this Addressing format. :raise InconsistencyError: Provided CAN ID value is incompatible with Extended Addressing format. :return: Normalized dictionary with the provided Addressing Information. """ if addressing_format != cls.ADDRESSING_FORMAT: raise ValueError(f"This class handles only one CAN Addressing format: {cls.ADDRESSING_FORMAT}. " f"Actual value: {addressing_format}") if (source_address, address_extension) != (None, None): raise UnusedArgumentError("Values of Source Address and Address Extension are not supported by " "Extended Addressing format and must be equal None.") addressing_type = AddressingType.validate_member(addressing_type) validate_raw_byte(target_address) # type: ignore if not cls.is_compatible_can_id(can_id=can_id, addressing_type=addressing_type): # type: ignore raise InconsistencyError("Provided value of CAN ID is incompatible with Extended Addressing format.") return CANAddressingParams(addressing_format=cls.ADDRESSING_FORMAT, addressing_type=addressing_type, can_id=can_id, # type: ignore target_address=target_address, source_address=source_address, address_extension=address_extension)
[docs] @staticmethod def is_compatible_can_id(can_id: int, addressing_type: Optional[AddressingType] = None) -> bool: """ Check whether provided CAN ID is consistent with Extended 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. """ return CanIdHandler.is_can_id(can_id)
[docs] @staticmethod def decode_can_id_ai_params(can_id: int) -> AbstractCanAddressingInformation.CanIdAIParams: """Decode Addressing Information parameters from CAN Identifier.""" return AbstractCanAddressingInformation.CanIdAIParams(addressing_type=None, target_address=None, source_address=None, priority=None)
[docs] @staticmethod def decode_data_bytes_ai_params( ai_data_bytes: RawBytesAlias) -> AbstractCanAddressingInformation.DataBytesAIParamsAlias: """ Decode Addressing Information parameters from CAN data bytes. :param ai_data_bytes: Data bytes containing Addressing Information. :return: Decoded Addressing Information parameters. """ validate_raw_bytes(ai_data_bytes, allow_empty=False) return AbstractCanAddressingInformation.DataBytesAIParamsAlias(target_address=ai_data_bytes[0])
[docs] @classmethod 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. """ validate_raw_byte(target_address) # type: ignore return bytearray([target_address]) # type: ignore