""" CAN Bus decoder for Chapter 10 data types Supports Controller Area Network Bus (0x78) """ import struct from typing import Dict, Any, Optional from .base import DataTypeDecoder, DecodedPayload class CANBusDecoder(DataTypeDecoder): """Decoder for CAN Bus type (0x78)""" def __init__(self): super().__init__() self.data_type_base = 0x78 self.data_type_name = "CAN Bus" self.supported_formats = [0x78] def can_decode(self, data_type: int) -> bool: return data_type == 0x78 def get_data_type_name(self, data_type: int) -> str: return "Controller Area Network Bus" def decode(self, payload: bytes, ch10_header: Dict[str, Any]) -> Optional[DecodedPayload]: """Decode CAN Bus payload""" decoded_data = {} errors = [] # Parse IPH iph = self._parse_intra_packet_header(payload) if iph: decoded_data.update(iph) data_start = iph['data_start'] else: data_start = 0 errors.append("Failed to parse intra-packet header") # Parse CAN messages messages = [] offset = data_start while offset + 16 <= len(payload): can_header = self._safe_unpack('= 100: # Limit output size break decoded_data['can_messages'] = messages decoded_data['message_count'] = len(messages) # Statistics if messages: extended_count = sum(1 for msg in messages if msg['extended_id']) remote_count = sum(1 for msg in messages if msg['remote_frame']) error_count = sum(1 for msg in messages if msg['error_frame']) decoded_data['statistics'] = { 'extended_frames': extended_count, 'remote_frames': remote_count, 'error_frames': error_count, 'standard_frames': len(messages) - extended_count } return DecodedPayload( data_type=0x78, data_type_name="Controller Area Network Bus", format_version=0, decoded_data=decoded_data, raw_payload=payload, errors=errors, metadata={'decoder': 'CANBusDecoder'} )