Beispiel #1
0
class FileHeader(Validatable):
    SCHEMA = [{
        "permissions": Types.OBJECT(FilePermissions),
        "properties": Types.OBJECT(FileProperties),
        "alp_command_file_id": Types.BYTE(),
        "interface_file_id": Types.BYTE(),
        "file_size": Types.INTEGER(min=0, max=0xFFFFFFFF),
        "allocated_size": Types.INTEGER(min=0, max=0xFFFFFFFF)
    }]

    def __init__(self, permissions, properties, alp_command_file_id,
                 interface_file_id, file_size, allocated_size):
        self.permissions = permissions
        self.properties = properties
        self.alp_command_file_id = alp_command_file_id
        self.interface_file_id = interface_file_id
        self.file_size = file_size
        self.allocated_size = allocated_size
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        permissions = FilePermissions.parse(s)
        properties = FileProperties.parse(s)
        alp_command_file_id = s.read("uint:8")
        interface_file_id = s.read("uint:8")
        file_size = s.read("uint:32")
        allocated_size = s.read("uint:32")
        return FileHeader(permissions, properties, alp_command_file_id,
                          interface_file_id, file_size, allocated_size)

    def __iter__(self):
        for byte in self.permissions:
            yield byte

        for byte in self.properties:
            yield byte

        yield self.alp_command_file_id
        yield self.interface_file_id
        for byte in bytearray(struct.pack(">I", self.file_size)):
            yield byte

        for byte in bytearray(struct.pack(">I", self.allocated_size)):
            yield byte

    def __eq__(self, other):
        if isinstance(other, FileHeader):
            return self.__dict__ == other.__dict__

        return False

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "permissions={}, properties=({}), alp_command_file_id={}, interface_file_id={}, file_size={}, allocated_size={}".format(
            self.permissions, self.properties, self.alp_command_file_id,
            self.interface_file_id, self.file_size, self.allocated_size)
Beispiel #2
0
class Offset(Validatable):

    SCHEMA = [{
        "id": Types.BYTE(),
        "size": Types.INTEGER([1]),
        "offset": Types.INTEGER(min=0, max=0xFF)
    }, {
        "id": Types.BYTE(),
        "size": Types.INTEGER([2]),
        "offset": Types.INTEGER(min=0, max=0xFFFF)
    }, {
        "id": Types.BYTE(),
        "size": Types.INTEGER([3]),
        "offset": Types.INTEGER(min=0, max=0xFFFFFF)
    }, {
        "id": Types.BYTE(),
        "size": Types.INTEGER([4]),
        "offset": Types.INTEGER(min=0, max=0xFFFFFFFF)
    }]

    def __init__(self, id=0, size=1, offset=0):
        self.id = id
        self.size = size
        self.offset = offset
        super(Offset, self).__init__()

    def __iter__(self):
        yield chr(self.id)

        byte = 0
        byte += (self.size - 1) << 6

        if self.size == 1:
            byte += self.offset
            yield byte
        else:
            offset = bytearray(struct.pack(">I", self.offset))
            if self.size == 2: offset = offset[2:]
            elif self.size == 3: offset = offset[1:]

            byte += offset[0]
            yield byte
            for byte in offset[1:]:
                yield byte

    def __str__(self):
        return "file-id={}, size={}, offset={}".format(self.id, self.size,
                                                       self.offset)
Beispiel #3
0
class FileHeaderOperand(Validatable):

    SCHEMA = [{
        "file_id": Types.BYTE(),
        "file_header": Types.OBJECT(FileHeader)
    }]

    def __init__(self, file_id, file_header):
        self.file_id = file_id
        self.file_header = file_header
        super(FileHeaderOperand, self).__init__()

    def __iter__(self):
        yield self.file_id
        for byte in self.file_header:
            yield byte

    @staticmethod
    def parse(s):
        file_id = s.read("uint:8")
        file_header = FileHeader.parse(s)
        return FileHeaderOperand(file_id=file_id, file_header=file_header)

    def __str__(self):
        return "file-id={}, header={}".format(self.file_id, self.file_header)
Beispiel #4
0
class Data(Validatable):

    SCHEMA = [{
        "offset": Types.OBJECT(Offset),
        "length": Types.BYTE(),
        "data": Types.BYTES()
    }]

    def __init__(self, data=[], offset=Offset()):
        self.offset = offset
        self.data = data
        super(Data, self).__init__()

    # for consistency with schema, e.g. if using generic attribute conversion, etc
    @property
    def length(self):
        return len(self.data)

    # the Python way ;-)
    def __len__(self):
        return self.length

    def __iter__(self):
        for byte in self.offset:
            yield byte
        yield chr(self.length)
        for byte in self.data:
            yield chr(byte)

    def __str__(self):
        return "{}, length={}, data={}".format(self.offset, self.length,
                                               self.data)
Beispiel #5
0
class Offset(Validatable):

  SCHEMA = [
    {
      "id"    : Types.BYTE(),
      "offset": Types.OBJECT(Length)
    }
  ]

  def __init__(self, id=0, offset=Length()):
    self.id     = id
    self.offset = offset
    super(Offset, self).__init__()

  @staticmethod
  def parse(s):
    id = s.read("uint:8")
    offset = Length.parse(s)
    return Offset(id=id, offset=offset)

  def __iter__(self):
    yield self.id
    for byte in self.offset: yield byte

  def __str__(self):
    return "file-id={}, offset={}".format(self.id, self.offset)
Beispiel #6
0
class SubProfile(Validatable):

    SCHEMA = [{
        "subband_bitmap": Types.BYTE(),
        "scan_automation_period": Types.OBJECT(CT)
    }]

    def __init__(self, subband_bitmap=0, scan_automation_period=CT()):
        self.subband_bitmap = subband_bitmap
        self.scan_automation_period = scan_automation_period
        super(SubProfile, self).__init__()

    @staticmethod
    def parse(s):
        subband_bitmap = s.read("uint:8")
        scan_automation_period = CT.parse(s)
        return SubProfile(subband_bitmap=subband_bitmap,
                          scan_automation_period=scan_automation_period)

    def __iter__(self):
        yield self.subband_bitmap
        for byte in self.scan_automation_period:
            yield byte

    def __str__(self):
        return pprint.PrettyPrinter().pformat(self.as_dict())
Beispiel #7
0
class Frame(Validatable):

    SCHEMA = [{
        "length": Types.BYTE(),
        "subnet": Types.BYTE(),
        "control": Types.OBJECT(Control),
        "target_address": Types.BYTES(),  # TODO max size?
        "d7anp_frame":
        Types.OBJECT(D7anpFrame),  # TODO assuming foreground frames for now
        "crc16": Types.BITS(
            16
        )  # TODO does not work, look into this later {'validator': validate_crc }
    }]

    def __init__(self, length, subnet, control, target_address, d7anp_frame,
                 crc16):
        self.length = length
        self.subnet = subnet
        self.control = control
        self.target_address = target_address
        self.d7anp_frame = d7anp_frame
        self.crc16 = crc16
        # TODO validate CRC

        super(Frame, self).__init__()

    # def validate_crc(self, value, error):
    #   raw_data = []
    #   raw_data.append(self.length)
    #   raw_data.append(self.subnet)
    #   raw_data.append(self.control)
    #   raw_data.append(self.target_address)
    #   raw_data.append(self.payload)
    #   crc = CRCCCITT().calculate(raw_data)

    def __iter__(self):
        yield self.length
        yield self.subnet
        for byte in self.control:
            yield byte
        for byte in self.target_address:
            yield byte
        for byte in self.d7anp_frame:
            yield byte
        yield self.crc16
Beispiel #8
0
class FileIdOperand(Validatable):

    SCHEMA = [{"file_id": Types.BYTE()}]

    def __init__(self, file_id):
        self.file_id = file_id
        super(FileIdOperand, self).__init__()

    def __iter__(self):
        yield self.file_id

    def __str__(self):
        return "file-id={}".format(self.file_id)
Beispiel #9
0
class BackgroundFrame(Validatable):

    SCHEMA = [{
        "subnet": Types.BYTE(),
        "control": Types.OBJECT(BackgroundFrameControl),
        "payload": Types.BITS(16),
        "crc16": Types.BITS(
            16
        )  # TODO does not work, look into this later {'validator': validate_crc }
    }]

    def __init__(self, subnet, control, payload, crc16):
        self.subnet = subnet
        self.control = control
        self.payload = payload
        self.crc16 = crc16
        # TODO validate CRC

        super(BackgroundFrame, self).__init__()

    # def validate_crc(self, value, error):
    #   raw_data = []
    #   raw_data.append(self.length)
    #   raw_data.append(self.subnet)
    #   raw_data.append(self.control)
    #   raw_data.append(self.target_address)
    #   raw_data.append(self.payload)
    #   crc = CRCCCITT().calculate(raw_data)

    @staticmethod
    def parse(s):
        subnet = s.read("int:8")
        control = BackgroundFrameControl.parse(s)
        payload = s.read("uint:16")
        crc = s.read("uint:16")

        return BackgroundFrame(subnet=subnet,
                               control=control,
                               payload=payload,
                               crc16=crc)

    def __iter__(self):
        yield self.subnet
        for byte in self.control:
            yield byte
        for byte in self.payload:
            yield byte
        yield self.crc16

    def __str__(self):
        return pprint.PrettyPrinter().pformat(self.as_dict())
Beispiel #10
0
class TagId(Validatable):

    SCHEMA = [{
        "tag_id": Types.BYTE(),
    }]

    def __init__(self, tag_id):
        self.tag_id = tag_id
        super(TagId, self).__init__()

    def __iter__(self):
        yield self.tag_id

    def __str__(self):
        return "tag_id={}".format(self.tag_id)
Beispiel #11
0
class Frame(Validatable):

  SCHEMA = [{
    "control": Types.OBJECT(Control),
    "origin_access_class": Types.BYTE(),
    "origin_access_id": Types.BYTES(), # TODO refactor to use OriginAddressee (subclass of addressee containing control and access_id)
    "d7atp_frame": Types.OBJECT(D7atpFrame)
  }]

  def __init__(self, control, origin_access_class, origin_access_id, d7atp_frame):
    self.control = control
    self.origin_access_class = origin_access_class
    self.origin_access_id = origin_access_id
    self.d7atp_frame = d7atp_frame # TODO
    super(Frame, self).__init__()

  @staticmethod
  def parse(bitstream, payload_length):
    control = Control.parse(bitstream)
    payload_length -= 1 # substract control

    origin_access_class = bitstream.read("uint:8")
    payload_length -= 1

    assert control.has_hopping == False, "Not implemented yet"
    assert control.nls_method == NlsMethod.NONE, "Not implemented yet"

    if not control.has_no_origin_access_id:
      if control.origin_id_type == IdType.VID:
        origin_access_id = map(ord, bitstream.read("bytes:2"))
        payload_length = payload_length - 2
      elif control.origin_id_type == IdType.UID:
        origin_access_id = map(ord, bitstream.read("bytes:8"))
        payload_length = payload_length - 8
      else:
        assert False
    else:
      origin_access_id = []

    #payload=map(ord,bitstream.read("bytes:" + str(payload_length)))
    d7atp_frame = D7atpFrame.parse(bitstream, payload_length)
    return Frame(control=control, origin_access_class=origin_access_class, origin_access_id=origin_access_id, d7atp_frame=d7atp_frame)

  def __iter__(self):
    for byte in self.control: yield byte
    yield self.origin_access_class
    for byte in self.origin_access_id: yield byte
    for byte in self.d7atp_frame: yield byte
Beispiel #12
0
class DataRequest(Validatable):

    SCHEMA = [{"offset": Types.OBJECT(Offset), "length": Types.BYTE()}]

    def __init__(self, length, offset=Offset()):
        self.offset = offset
        self.length = length
        super(DataRequest, self).__init__()

    def __iter__(self):
        for byte in self.offset:
            yield byte
        yield chr(self.length)

    def __str__(self):
        return "{}, length={}".format(self.offset, self.length)
Beispiel #13
0
class FileHeaderOperand(Validatable):

    SCHEMA = [{
        "file_id": Types.BYTE(),
        "file_header": Types.OBJECT(FileHeader)
    }]

    def __init__(self, file_id, file_header):
        self.file_id = file_id
        self.file_header = file_header
        super(FileHeaderOperand, self).__init__()

    def __iter__(self):
        yield self.file_id
        for byte in self.file_header:
            yield byte

    def __str__(self):
        return "file-id={}, header={}".format(self.file_id, self.file_header)
Beispiel #14
0
class InterfaceStatusOperand(Validatable):

    SCHEMA = [{
        "interface_id": Types.BYTE(),
        "interface_status": Types.OBJECT(Status, nullable=True)
    }]

    def __init__(self, interface_id, interface_status):
        self.interface_id = interface_id
        self.interface_status = interface_status
        super(InterfaceStatusOperand, self).__init__()

    def __iter__(self):
        yield self.interface_id
        for byte in self.interface_status:
            yield byte

    def __str__(self):
        return "interface-id={}, status={}".format(self.interface_id,
                                                   self.interface_status)
Beispiel #15
0
class InterfaceConfiguration(Validatable):

    SCHEMA = [{
        "interface_id": Types.BYTE(),
        "interface_configuration": Types.OBJECT(Configuration)
    }]

    def __init__(self, interface_id, interface_configuration):
        self.interface_id = interface_id
        self.interface_configuration = interface_configuration
        super(InterfaceConfiguration, self).__init__()

    def __iter__(self):
        yield self.interface_id
        for byte in self.interface_configuration:
            yield byte

    def __str__(self):
        return "interface-id={}, status={}".format(
            self.interface_id, self.interface_configuration)
Beispiel #16
0
class Status(Validatable):

    SCHEMA = [{
        "channel_header": Types.OBJECT(ChannelHeader),
        "channel_index": Types.INTEGER(),
        "rx_level": Types.BYTE(),
        "link_budget": Types.BYTE(),
        "target_rx_level": Types.BYTE(),
        "nls": Types.BOOLEAN(),
        "missed": Types.BOOLEAN(),
        "retry": Types.BOOLEAN(),
        "ucast": Types.BOOLEAN(),
        "fifo_token": Types.BYTE(),
        "seq_nr": Types.BYTE(),
        "response_to": Types.OBJECT(CT),
        "addressee": Types.OBJECT(Addressee)
    }]

    def __init__(self, channel_header, channel_index, rx_level, link_budget,
                 target_rx_level, nls, missed, retry, unicast, fifo_token,
                 seq_nr, response_to, addressee):
        self.channel_header = channel_header
        self.channel_index = channel_index
        self.rx_level = rx_level
        self.link_budget = link_budget
        self.target_rx_level = target_rx_level
        self.nls = nls
        self.missed = missed
        self.retry = retry
        self.unicast = unicast
        self.fifo_token = fifo_token
        self.seq_nr = seq_nr
        self.response_to = response_to
        self.addressee = addressee
        super(Status, self).__init__()

    @staticmethod
    def parse(s):
        channel_header = ChannelHeader.parse(s)
        channel_index = s.read("uint:16")
        rx_level = s.read("int:8")
        link_budget = s.read("uint:8")
        target_rx_level = s.read("uint:8")
        nls = s.read("bool")
        missed = s.read("bool")
        retry = s.read("bool")
        unicast = s.read("bool")
        _ = s.read("pad:4")
        fifo_token = s.read("uint:8")
        seq_nr = s.read("uint:8")
        response_to = CT.parse(s)
        addressee = Addressee.parse(s)

        return Status(channel_header=channel_header,
                      channel_index=channel_index,
                      rx_level=rx_level,
                      link_budget=link_budget,
                      target_rx_level=target_rx_level,
                      nls=nls,
                      missed=missed,
                      retry=retry,
                      unicast=unicast,
                      fifo_token=fifo_token,
                      seq_nr=seq_nr,
                      response_to=response_to,
                      addressee=addressee)

    def __iter__(self):
        for byte in self.channel_header:
            yield byte
        for byte in bytearray(struct.pack("<h", self.channel_index)):
            yield byte
        yield self.rx_level
        yield self.link_budget
        yield self.target_rx_level
        byte = 0
        if self.nls: byte |= 1 << 7
        if self.missed: byte |= 1 << 6
        if self.retry: byte |= 1 << 5
        if self.unicast: byte |= 1 << 4
        yield byte
        yield chr(self.fifo_token)
        yield chr(self.seq_nr)
        for byte in self.response_to:
            yield byte
        for byte in self.addressee:
            yield byte

    def __str__(self):
        return "unicast={}, nls={}, retry={}, missed={}, fifo_token={}, rx_level={}, seq_nr={}, target_rx_level={}, " \
               "addressee={}, response_to={}, link_budget={}, channel_header={}, channel_index={}".format(
          self.unicast,
          self.nls,
          self.retry,
          self.missed,
          self.fifo_token,
          self.rx_level,
          self.seq_nr,
          self.target_rx_level,
          self.addressee,
          self.response_to,
          self.link_budget,
          self.channel_header,
          self.channel_index
        )
Beispiel #17
0
class Frame(Validatable):

    SCHEMA = [{
        "length": Types.BYTE(),
        "subnet": Types.BYTE(),
        "control": Types.OBJECT(Control),
        "target_address": Types.BYTES(),  # TODO max size?
        "d7anp_frame":
        Types.OBJECT(D7anpFrame),  # TODO assuming foreground frames for now
        "crc16": Types.BITS(
            16
        )  # TODO does not work, look into this later {'validator': validate_crc }
    }]

    def __init__(self, length, subnet, control, target_address, d7anp_frame,
                 crc16):
        self.length = length
        self.subnet = subnet
        self.control = control
        self.target_address = target_address
        self.d7anp_frame = d7anp_frame
        self.crc16 = crc16
        # TODO validate CRC

        super(Frame, self).__init__()

    # def validate_crc(self, value, error):
    #   raw_data = []
    #   raw_data.append(self.length)
    #   raw_data.append(self.subnet)
    #   raw_data.append(self.control)
    #   raw_data.append(self.target_address)
    #   raw_data.append(self.payload)
    #   crc = CRCCCITT().calculate(raw_data)

    @staticmethod
    def parse(s):
        length = s.read("int:8")
        subnet = s.read("int:8")
        control = Control.parse(s)
        payload_length = length - 4  # substract subnet, control, crc
        if control.id_type == IdType.VID:
            target_address = map(ord, s.read("bytes:2"))
            payload_length = payload_length - 2
        elif control.id_type == IdType.UID:
            target_address = map(ord, s.read("bytes:8"))
            payload_length = payload_length - 8
        else:
            target_address = []

        return Frame(length=length,
                     subnet=subnet,
                     control=control,
                     target_address=target_address,
                     d7anp_frame=D7anpFrame.parse(s, payload_length),
                     crc16=s.read("uint:16"))

    def __iter__(self):
        yield self.length
        yield self.subnet
        for byte in self.control:
            yield byte
        for byte in self.target_address:
            yield byte
        for byte in self.d7anp_frame:
            yield byte
        yield self.crc16
Beispiel #18
0
class Addressee(Validatable):

    # addressee ID length
    ID_LENGTH_NBID = 1
    ID_LENGTH_NOID = 0
    ID_LENGTH_VID = 2
    ID_LENGTH_UID = 8

    SCHEMA = [
        {
            # void identifier with reached devices estimation
            "id_type": Types.ENUM(IdType, allowedvalues=[IdType.NBID]),
            "nls_method": Types.ENUM(NlsMethod),
            "access_class": Types.BYTE(),
            "id": Types.OBJECT(CT)
        },
        {
            # void identifier without reached devices estimation
            "id_type": Types.ENUM(IdType, allowedvalues=[IdType.NOID]),
            "nls_method": Types.ENUM(NlsMethod),
            "access_class": Types.BYTE(),
            "id": Types.INTEGER([None])
        },
        {
            # virtual
            "id_type": Types.ENUM(IdType, allowedvalues=[IdType.VID]),
            "nls_method": Types.ENUM(NlsMethod),
            "access_class": Types.BYTE(),
            "id": Types.INTEGER(min=0, max=0xFFFF)
        },
        {
            # unicast
            "id_type": Types.ENUM(IdType, allowedvalues=[IdType.UID]),
            "nls_method": Types.ENUM(NlsMethod),
            "access_class": Types.BYTE(),
            "id": Types.INTEGER(min=0, max=0xFFFFFFFFFFFFFFFF)
        }
    ]

    #  SCHEMA = [
    #    {
    #      "id_type"   : Types.INTEGER(IdType.ALL),
    #      "cl"        : Types.BITS(4),
    #      "id_length" : Types.INTEGER([0, 2, 8]),
    #      "id"        : Types.INTEGER(min=0, max=0xFFFFFFFFFFFFFFFF)
    #    }
    #  ]

    def __init__(self,
                 access_class=0,
                 id_type=IdType.NOID,
                 id=None,
                 nls_method=NlsMethod.NONE):
        self.id_type = id_type
        self.access_class = access_class
        self.id = id
        self.nls_method = nls_method
        super(Addressee, self).__init__()

    @property
    def id_length(self):
        return Addressee.length_for(id_type=self.id_type)

    @classmethod
    def length_for(self, id_type):
        if id_type == IdType.NBID: return Addressee.ID_LENGTH_NBID
        if id_type == IdType.NOID: return Addressee.ID_LENGTH_NOID
        if id_type == IdType.VID: return Addressee.ID_LENGTH_VID
        if id_type == IdType.UID: return Addressee.ID_LENGTH_UID

    @staticmethod
    def parse(s):
        _ = s.read("pad:2")
        id_type = IdType(s.read("uint:2"))
        nls_method = NlsMethod(s.read("uint:4"))
        cl = s.read("uint:8")
        l = Addressee.length_for(id_type)
        id = s.read("uint:" + str(l * 8)) if l > 0 else None
        if id_type == IdType.NBID:
            id = CT(id)

        return Addressee(id_type=id_type,
                         access_class=cl,
                         id=id,
                         nls_method=nls_method)

    def __iter__(self):
        byte = 0
        # pad 2 << 7 << 6
        byte |= self.id_type.value << 4
        byte += self.nls_method.value
        yield byte
        yield self.access_class
        if self.id_length > 0:
            id_value = self.id
            if self.id_type == IdType.NBID:
                # self.id is a CT
                id_value = self.id.compressed_value()

            id = bytearray(struct.pack(">Q", id_value))[8 - self.id_length:]
            for byte in id:
                yield byte

    def __str__(self):
        return "ac={}, id_type={}, id={}".format(self.access_class,
                                                 self.id_type, self.id)
Beispiel #19
0
class Status(Validatable):

    SCHEMA = [{
        "channel_header": Types.BYTE(),  # TODO parse
        "channel_index": Types.INTEGER(),
        "rx_level": Types.BYTE(),
        "link_budget": Types.BYTE(),
        "target_rx_level": Types.BYTE(),
        "nls": Types.BOOLEAN(),
        "missed": Types.BOOLEAN(),
        "retry": Types.BOOLEAN(),
        "ucast": Types.BOOLEAN(),
        "fifo_token": Types.BYTE(),
        "seq_nr": Types.BYTE(),
        "response_to": Types.OBJECT(CT),
        "addressee": Types.OBJECT(Addressee)
    }]

    def __init__(self, channel_header, channel_index, rx_level, link_budget,
                 target_rx_level, nls, missed, retry, unicast, fifo_token,
                 seq_nr, response_to, addressee):
        self.channel_header = channel_header
        self.channel_index = channel_index
        self.rx_level = rx_level
        self.link_budget = link_budget
        self.target_rx_level = target_rx_level
        self.nls = nls
        self.missed = missed
        self.retry = retry
        self.unicast = unicast
        self.fifo_token = fifo_token
        self.seq_nr = seq_nr
        self.response_to = response_to
        self.addressee = addressee
        super(Status, self).__init__()

    def __iter__(self):
        yield self.channel_header
        for byte in bytearray(struct.pack("<h", self.channel_index)):
            yield byte
        yield self.rx_level
        yield self.link_budget
        yield self.target_rx_level
        byte = 0
        if self.nls: byte |= 1 << 7
        if self.missed: byte |= 1 << 6
        if self.retry: byte |= 1 << 5
        if self.unicast: byte |= 1 << 4
        yield byte
        yield chr(self.fifo_token)
        yield chr(self.seq_nr)
        for byte in self.response_to:
            yield byte
        for byte in self.addressee:
            yield byte

    def __str__(self):
        return "unicast={}, nls={}, retry={}, missed={}, fifo_token={}, rx_level={}, " \
              "seq_nr={}, target_rx_level={}, addressee={}, response_to={}, link_budget={}, channel_header={}".format(
          self.unicast,
          self.nls,
          self.retry,
          self.missed,
          self.fifo_token,
          self.rx_level,
          self.seq_nr,
          self.target_rx_level,
          self.addressee,
          self.response_to,
          self.link_budget,
          self.channel_header
        )