1from dataclasses import dataclass, field 2from typing import Tuple 3 4 5@dataclass(init=False) 6class Address: 7 address: bytes = field(default=bytes([0, 0, 0, 0, 0, 0])) 8 9 def __init__(self, address=None): 10 if not address: 11 self.address = bytes([0, 0, 0, 0, 0, 0]) 12 elif isinstance(address, Address): 13 self.address = address.address 14 elif isinstance(address, str): 15 self.address = bytes([int(b, 16) for b in address.split(':')]) 16 elif isinstance(address, bytes) and len(address) == 6: 17 self.address = address 18 elif isinstance(address, bytes): 19 address = address.decode('utf-8') 20 self.address = bytes([int(b, 16) for b in address.split(':')]) 21 else: 22 raise Exception(f'unsupported address type: {address}') 23 24 def from_str(address: str) -> 'Address': 25 return Address(bytes([int(b, 16) for b in address.split(':')])) 26 27 def parse(span: bytes) -> Tuple['Address', bytes]: 28 assert len(span) >= 6 29 return (Address(bytes(reversed(span[:6]))), span[6:]) 30 31 def parse_all(span: bytes) -> 'Address': 32 assert (len(span) == 6) 33 return Address(bytes(reversed(span))) 34 35 def serialize(self) -> bytes: 36 return bytes(reversed(self.address)) 37 38 def __repr__(self) -> str: 39 return ':'.join([f'{b:02x}' for b in self.address]) 40 41 @property 42 def size(self) -> int: 43 return 6 44 45 46@dataclass(init=False) 47class ClassOfDevice: 48 class_of_device: int = 0 49 50 def __init__(self, class_of_device=None): 51 if not class_of_device: 52 self.class_of_device = 0 53 elif isinstance(class_of_device, int): 54 self.class_of_device = class_of_device 55 elif isinstance(class_of_device, bytes): 56 self.class_of_device = int.from_bytes(class_of_device, byteorder='little') 57 else: 58 raise Exception(f'unsupported class of device type: {class_of_device}') 59 60 def parse(span: bytes) -> Tuple['ClassOfDevice', bytes]: 61 assert len(span) >= 3 62 return (ClassOfDevice(span[:3]), span[3:]) 63 64 def parse_all(span: bytes) -> 'ClassOfDevice': 65 assert len(span) == 3 66 return ClassOfDevice(span) 67 68 def serialize(self) -> bytes: 69 return int.to_bytes(self.class_of_device, length=3, byteorder='little') 70 71 def __repr__(self) -> str: 72 return f'{self.class_of_device:06x}' 73 74 @property 75 def size(self) -> int: 76 return 3 77