# Path: cbus/common.py
# class CAL(IntEnum):
#     RESET = 0x08
#     RECALL = 0x1a
#     IDENTIFY = 0x21
#     GET_STATUS = 0x2a
#     ACKNOWLEDGE = 0x32
# 
#     # These are bit-masks
#     REPLY = 0x80
#     STANDARD_STATUS = 0xc0
#     EXTENDED_STATUS = 0xe0
# 
# class Application(IntEnum):
#     TEMPERATURE = 0x19
#     LIGHTING_FIRST = LIGHTING_30 = 0x30
#     LIGHTING_31 = 0x31
#     LIGHTING_32 = 0x32
#     LIGHTING_33 = 0x33
#     LIGHTING_34 = 0x34
#     LIGHTING_35 = 0x35
#     LIGHTING_36 = 0x36
#     LIGHTING_37 = 0x37
#     LIGHTING = LIGHTING_38 = 0x38
#     LIGHTING_39 = 0x39
#     LIGHTING_3a = 0x3a
#     LIGHTING_3b = 0x3b
#     LIGHTING_3c = 0x3c
#     LIGHTING_3d = 0x3d
#     LIGHTING_3e = 0x3e
#     LIGHTING_3f = 0x3f
#     LIGHTING_40 = 0x40
#     LIGHTING_41 = 0x41
#     LIGHTING_42 = 0x42
#     LIGHTING_43 = 0x43
#     LIGHTING_44 = 0x44
#     LIGHTING_45 = 0x45
#     LIGHTING_46 = 0x46
#     LIGHTING_47 = 0x47
#     LIGHTING_48 = 0x48
#     LIGHTING_49 = 0x49
#     LIGHTING_4a = 0x4a
#     LIGHTING_4b = 0x4b
#     LIGHTING_4c = 0x4c
#     LIGHTING_4d = 0x4d
#     LIGHTING_4e = 0x4e
#     LIGHTING_4f = 0x4f
#     LIGHTING_50 = 0x50
#     LIGHTING_51 = 0x51
#     LIGHTING_52 = 0x52
#     LIGHTING_53 = 0x53
#     LIGHTING_54 = 0x54
#     LIGHTING_55 = 0x55
#     LIGHTING_56 = 0x56
#     LIGHTING_57 = 0x57
#     LIGHTING_58 = 0x58
#     LIGHTING_59 = 0x59
#     LIGHTING_5a = 0x5a
#     LIGHTING_5b = 0x5b
#     LIGHTING_5c = 0x5c
#     LIGHTING_5d = 0x5d
#     LIGHTING_5e = 0x5e
#     LIGHTING_LAST = LIGHTING_5f = 0x5f
#     CLOCK = 0xDF
#     ENABLE = 0xCB
#     MASTER_APPLICATION = STATUS_REQUEST = 0xff
# 
# def add_cbus_checksum(i: bytes) -> bytes:
#     """
#     Appends a C-Bus checksum to a given message.
# 
#     :param i: The C-Bus message to append a checksum to. Must not be in base16
#               format.
#     :type i: bytes
# 
#     :returns: The C-Bus message with the checksum appended to it.
#     :rtype: bytes
#     """
#     c = cbus_checksum(i)
#     return i + bytes([c])
# 
# Path: cbus/protocol/cal/report.py
# class BinaryStatusReport(StatusReport, Sequence[GroupState]):
#     _group_states: Sequence[GroupState]
# 
#     def __getitem__(self, i: int) -> GroupState:
#         return self._group_states[i]
# 
#     def __len__(self) -> int:
#         return len(self._group_states)
# 
#     def __iter__(self) -> Iterator[GroupState]:
#         return iter(self._group_states)
# 
#     @classmethod
#     def decode(cls, data: bytes) -> BinaryStatusReport:
#         states = []
#         for c in data:
#             states += [
#                 GroupState(c & 0x3),
#                 GroupState((c >> 2) & 0x03),
#                 GroupState((c >> 4) & 0x03),
#                 GroupState((c >> 6) & 0x03)]
# 
#         return BinaryStatusReport(states)
# 
#     @property
#     def block_type(self) -> ExtendedCALType:
#         return ExtendedCALType.BINARY
# 
#     def encode(self) -> bytes:
#         group_states = list(self._group_states)
#         r = len(group_states) % 4
#         if r != 0:
#             # add padding
#             group_states += [GroupState.MISSING] * (4 - r)
# 
#         # iterate 4 groups at a time
#         o = []
#         for p in range(0, len(group_states), 4):
#             o.append(group_states[p] |
#                      (group_states[p + 1] << 2) |
#                      (group_states[p + 2] << 4) |
#                      (group_states[p + 3] << 6))
# 
#         return bytes(o)
# 
# Path: cbus/protocol/base_packet.py
# class SpecialServerPacket(_SpecialPacket, abc.ABC):
#     """
#     PCI -> Client has some special packets that we make subclasses of this,
#     because they're different to regular packets.
# 
#     These have non-standard serialisation methods.
#     """
#     pass


from base64 import b16encode
from dataclasses import dataclass
from typing import Union
from cbus.common import CAL, Application, add_cbus_checksum
from cbus.protocol.cal.report import BinaryStatusReport
from cbus.protocol.base_packet import SpecialServerPacket

        return bytes([
            CAL.STANDARD_STATUS | (len(report) + 3),
            self.child_application & 0xff,
            self.block_start & 0xff]) + report

    def encode_packet(self) -> bytes:
        """
        Standard CALs can be also sent as a packet without headers directly
        onto the network.

        This adds a checksum (if checksum=True) and base16 encodes the CAL
        like it was a normal packet.
        """
        # checksum it, if needed.
        p = self.encode()

        if self.checksum:
            p = add_cbus_checksum(p)

        return b16encode(p)

    @classmethod
    def decode_cal(cls, data: bytes) -> StandardCAL:
        # expects a standard status cal, cropped to exact size, starting
        # from the application byte
        child_application = data[0]
        block_start = data[1]
        payload = data[2:]


# Path: cbus/common.py
# class CAL(IntEnum):
#     RESET = 0x08
#     RECALL = 0x1a
#     IDENTIFY = 0x21
#     GET_STATUS = 0x2a
#     ACKNOWLEDGE = 0x32
# 
#     # These are bit-masks
#     REPLY = 0x80
#     STANDARD_STATUS = 0xc0
#     EXTENDED_STATUS = 0xe0
# 
# class Application(IntEnum):
#     TEMPERATURE = 0x19
#     LIGHTING_FIRST = LIGHTING_30 = 0x30
#     LIGHTING_31 = 0x31
#     LIGHTING_32 = 0x32
#     LIGHTING_33 = 0x33
#     LIGHTING_34 = 0x34
#     LIGHTING_35 = 0x35
#     LIGHTING_36 = 0x36
#     LIGHTING_37 = 0x37
#     LIGHTING = LIGHTING_38 = 0x38
#     LIGHTING_39 = 0x39
#     LIGHTING_3a = 0x3a
#     LIGHTING_3b = 0x3b
#     LIGHTING_3c = 0x3c
#     LIGHTING_3d = 0x3d
#     LIGHTING_3e = 0x3e
#     LIGHTING_3f = 0x3f
#     LIGHTING_40 = 0x40
#     LIGHTING_41 = 0x41
#     LIGHTING_42 = 0x42
#     LIGHTING_43 = 0x43
#     LIGHTING_44 = 0x44
#     LIGHTING_45 = 0x45
#     LIGHTING_46 = 0x46
#     LIGHTING_47 = 0x47
#     LIGHTING_48 = 0x48
#     LIGHTING_49 = 0x49
#     LIGHTING_4a = 0x4a
#     LIGHTING_4b = 0x4b
#     LIGHTING_4c = 0x4c
#     LIGHTING_4d = 0x4d
#     LIGHTING_4e = 0x4e
#     LIGHTING_4f = 0x4f
#     LIGHTING_50 = 0x50
#     LIGHTING_51 = 0x51
#     LIGHTING_52 = 0x52
#     LIGHTING_53 = 0x53
#     LIGHTING_54 = 0x54
#     LIGHTING_55 = 0x55
#     LIGHTING_56 = 0x56
#     LIGHTING_57 = 0x57
#     LIGHTING_58 = 0x58
#     LIGHTING_59 = 0x59
#     LIGHTING_5a = 0x5a
#     LIGHTING_5b = 0x5b
#     LIGHTING_5c = 0x5c
#     LIGHTING_5d = 0x5d
#     LIGHTING_5e = 0x5e
#     LIGHTING_LAST = LIGHTING_5f = 0x5f
#     CLOCK = 0xDF
#     ENABLE = 0xCB
#     MASTER_APPLICATION = STATUS_REQUEST = 0xff
# 
# def add_cbus_checksum(i: bytes) -> bytes:
#     """
#     Appends a C-Bus checksum to a given message.
# 
#     :param i: The C-Bus message to append a checksum to. Must not be in base16
#               format.
#     :type i: bytes
# 
#     :returns: The C-Bus message with the checksum appended to it.
#     :rtype: bytes
#     """
#     c = cbus_checksum(i)
#     return i + bytes([c])
# 
# Path: cbus/protocol/cal/report.py
# class BinaryStatusReport(StatusReport, Sequence[GroupState]):
#     _group_states: Sequence[GroupState]
# 
#     def __getitem__(self, i: int) -> GroupState:
#         return self._group_states[i]
# 
#     def __len__(self) -> int:
#         return len(self._group_states)
# 
#     def __iter__(self) -> Iterator[GroupState]:
#         return iter(self._group_states)
# 
#     @classmethod
#     def decode(cls, data: bytes) -> BinaryStatusReport:
#         states = []
#         for c in data:
#             states += [
#                 GroupState(c & 0x3),
#                 GroupState((c >> 2) & 0x03),
#                 GroupState((c >> 4) & 0x03),
#                 GroupState((c >> 6) & 0x03)]
# 
#         return BinaryStatusReport(states)
# 
#     @property
#     def block_type(self) -> ExtendedCALType:
#         return ExtendedCALType.BINARY
# 
#     def encode(self) -> bytes:
#         group_states = list(self._group_states)
#         r = len(group_states) % 4
#         if r != 0:
#             # add padding
#             group_states += [GroupState.MISSING] * (4 - r)
# 
#         # iterate 4 groups at a time
#         o = []
#         for p in range(0, len(group_states), 4):
#             o.append(group_states[p] |
#                      (group_states[p + 1] << 2) |
#                      (group_states[p + 2] << 4) |
#                      (group_states[p + 3] << 6))
# 
#         return bytes(o)
# 
# Path: cbus/protocol/base_packet.py
# class SpecialServerPacket(_SpecialPacket, abc.ABC):
#     """
#     PCI -> Client has some special packets that we make subclasses of this,
#     because they're different to regular packets.
# 
#     These have non-standard serialisation methods.
#     """
#     pass


# Path: cbus/protocol/cal/standard.py
from base64 import b16encode
from dataclasses import dataclass
from typing import Union
from cbus.common import CAL, Application, add_cbus_checksum
from cbus.protocol.cal.report import BinaryStatusReport
from cbus.protocol.base_packet import SpecialServerPacket


        return bytes([
            CAL.STANDARD_STATUS | (len(report) + 3),
            self.child_application & 0xff,
            self.block_start & 0xff]) + report

    def encode_packet(self) -> bytes:
        """
        Standard CALs can be also sent as a packet without headers directly
        onto the network.

        This adds a checksum (if checksum=True) and base16 encodes the CAL
        like it was a normal packet.
        """
        # checksum it, if needed.
        p = self.encode()

        if self.checksum:
            p = add_cbus_checksum(p)

        return b16encode(p)

    @classmethod
    def decode_cal(cls, data: bytes) -> StandardCAL:
        # expects a standard status cal, cropped to exact size, starting
        # from the application byte
        child_application = data[0]
        block_start = data[1]
        payload = data[2:]


        report = BinaryStatusReport.decode(payload)