Exemple #1
0
class DllConfigFile(File, Validatable):
    SCHEMA = [{
        "active_access_class": Types.INTEGER(min=0, max=0xFF),
        "vid": Types.INTEGER(min=0, max=0xFFFF)
        # TODO others
    }]

    def __init__(self, active_access_class=0, vid=0xFFFF):
        self.active_access_class = active_access_class
        self.vid = vid
        Validatable.__init__(self)
        File.__init__(self, SystemFileIds.DLL_CONFIG.value, 6)

    @staticmethod
    def parse(s):
        ac = s.read("uint:8")
        vid = s.read("uint:16")
        return DllConfigFile(active_access_class=ac, vid=vid)

    def __iter__(self):
        yield self.active_access_class
        for byte in bytearray(struct.pack(">H", self.vid)):
            yield byte

    def __str__(self):
        return "active_access_class={}, vid={}".format(
            self.active_access_class, self.vid)
Exemple #2
0
class Frame(Validatable):

    SCHEMA = [{
        "control": Types.OBJECT(Control),
        "dialog_id": Types.INTEGER(min=0, max=255),
        "transaction_id": Types.INTEGER(min=0, max=255),
        "ack_template": Types.OBJECT(nullable=True),  # TODO
        "alp_command": Types.OBJECT(Command)
    }]

    def __init__(self, control, dialog_id, transaction_id, ack_template,
                 alp_command):
        self.control = control
        self.dialog_id = dialog_id
        self.transaction_id = transaction_id
        self.ack_template = ack_template
        self.alp_command = alp_command
        super(Frame, self).__init__()

    def __iter__(self):
        for byte in self.control:
            yield byte
        yield self.dialog_id
        yield self.transaction_id
        for byte in self.ack_template:
            yield byte
        for byte in self.alp_command:
            yield byte
Exemple #3
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)
class EngineeringModeFile(File, Validatable):

    SCHEMA = [{
        "mode": Types.ENUM(EngineeringModeMode),
        "flags": Types.INTEGER(min=0, max=255),
        "timeout": Types.INTEGER(min=0, max=255),
        "channel_id": Types.OBJECT(ChannelID),
        "eirp": Types.INTEGER(min=-128, max=127)
    }]

    def __init__(self,
                 mode=EngineeringModeMode.ENGINEERING_MODE_MODE_OFF,
                 flags=0,
                 timeout=0,
                 channel_id=ChannelID(channel_header=ChannelHeader(
                     ChannelCoding.PN9, ChannelClass.LO_RATE,
                     ChannelBand.BAND_868),
                                      channel_index=0),
                 eirp=0):
        self.mode = mode
        self.flags = flags
        self.timeout = timeout
        self.channel_id = channel_id
        self.eirp = eirp
        File.__init__(self, SystemFileIds.ENGINEERING_MODE, 9)
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        mode = EngineeringModeMode(int(s.read("uint:8")))
        flags = s.read("uint:8")
        timeout = s.read("uint:8")
        channel_id = ChannelID.parse(s)
        eirp = s.read("int:8")
        return EngineeringModeFile(mode=mode,
                                   flags=flags,
                                   timeout=timeout,
                                   channel_id=channel_id,
                                   eirp=eirp)

    def __iter__(self):
        yield int(self.mode.value)
        yield self.flags
        yield self.timeout
        for byte in self.channel_id:
            yield byte

        for byte in bytearray(struct.pack(">b", self.eirp)):
            yield byte
        yield 0
        yield 0

    def __str__(self):
        return "mode={}, flags={}, timeout={}, channel_id={{{}}}, eirp={}".format(
            self.mode, hex(self.flags), self.timeout, self.channel_id,
            self.eirp)
Exemple #5
0
class SubBand(Validatable):
    # TODO update to D7AP v1.1

    SCHEMA = [{
        "channel_index_start": Types.INTEGER(min=0, max=0xFFFF),
        "channel_index_end": Types.INTEGER(min=0, max=0xFFFF),
        "eirp": Types.INTEGER(min=-128, max=127),
        "cca": Types.INTEGER(min=0, max=255),
        "duty": Types.INTEGER(min=0, max=255),
    }]

    def __init__(self,
                 channel_index_start=0,
                 channel_index_end=0,
                 eirp=0,
                 cca=86,
                 duty=255):
        self.channel_index_start = channel_index_start
        self.channel_index_end = channel_index_end
        self.eirp = eirp
        self.cca = cca
        self.duty = duty
        super(SubBand, self).__init__()

    def __iter__(self):
        for byte in bytearray(struct.pack(">H", self.channel_index_start)):
            yield byte
        for byte in bytearray(struct.pack(">H", self.channel_index_end)):
            yield byte
        for byte in bytearray(struct.pack("b", self.eirp)):
            yield byte
        yield self.cca
        yield self.duty

    @staticmethod
    def parse(s):
        channel_index_start = struct.unpack(">H", s.read("bytes:2"))[0]
        channel_index_end = struct.unpack(">H", s.read("bytes:2"))[0]
        eirp = s.read("int:8")
        cca = s.read("uint:8")
        duty = s.read("uint:8")

        return SubBand(channel_index_start=channel_index_start,
                       channel_index_end=channel_index_end,
                       eirp=eirp,
                       cca=cca,
                       duty=duty)

    def __str__(self):
        return "channel_index_start={}, channel_index_end={}, eirp={}, cca={}, duty={}".format(
            self.channel_index_start, self.channel_index_end, self.eirp,
            self.cca, self.duty)
class FirmwareVersionFile(File, Validatable):

    SCHEMA = [{
        "d7a_protocol_version_major": Types.INTEGER(min=0, max=255),
        "d7a_protocol_version_minor": Types.INTEGER(min=0, max=255),
        # custom fields, specific to oss7
        "application_name": Types.STRING(maxlength=6),
        "git_sha1": Types.STRING(maxlength=7)
    }]

    def __init__(self,
                 d7a_protocol_version_major=0,
                 d7a_protocol_version_minor=0,
                 application_name="",
                 git_sha1=""):
        self.d7a_protocol_version_major = d7a_protocol_version_major
        self.d7a_protocol_version_minor = d7a_protocol_version_minor
        self.application_name = application_name
        self.git_sha1 = git_sha1
        Validatable.__init__(self)
        File.__init__(self, SystemFileIds.FIRMWARE_VERSION.value, 15)

    @property
    def d7ap_version(self):
        return str(self.d7a_protocol_version_major) + '.' + str(
            self.d7a_protocol_version_minor)

    @staticmethod
    def parse(s):
        major = s.read("uint:8")
        minor = s.read("uint:8")
        application_name = s.read("bytes:6").decode("ascii")
        git_sha1 = s.read("bytes:7").decode("ascii")
        return FirmwareVersionFile(d7a_protocol_version_major=major,
                                   d7a_protocol_version_minor=minor,
                                   application_name=application_name,
                                   git_sha1=git_sha1)

    def __iter__(self):
        yield self.d7a_protocol_version_major
        yield self.d7a_protocol_version_minor

        for byte in bytearray(self.application_name.encode("ASCII").ljust(6)):
            yield byte

        for byte in bytearray(self.git_sha1.encode("ASCII").ljust(7)):
            yield byte

    def __str__(self):
        return "d7ap v{}, application_name={}, git_sha1={}".format(
            self.d7ap_version, self.application_name, self.git_sha1)
Exemple #7
0
class DllConfigFile(File, Validatable):
    SCHEMA = [{
        "active_access_class": Types.INTEGER(min=0, max=0xFF),
        "LQ_filter": Types.INTEGER(min=0, max=0xFF),
        "NF_CTRL": Types.INTEGER(min=0, max=0xFF),
        "RX_NF_method_parameter": Types.INTEGER(min=0, max=0xFF),
        "TX_NF_method_parameter": Types.INTEGER(min=0, max=0xFF)
    }]

    def __init__(self,
                 active_access_class=0,
                 lq_filter=0x00,
                 nf_ctrl=0x00,
                 rx_nf_method_parameter=0x00,
                 tx_nf_method_parameter=0x00):
        self.active_access_class = active_access_class
        self.lq_filter = lq_filter
        self.nf_ctrl = nf_ctrl
        self.rx_nf_method_parameter = rx_nf_method_parameter
        self.tx_nf_method_parameter = tx_nf_method_parameter
        File.__init__(self, SystemFileIds.DLL_CONFIG.value, 7)
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        ac = s.read("uint:8")
        _rfu = s.read("uint:16")
        lq_filter = s.read("uint:8")
        nf_ctrl = s.read("uint:8")
        rx_nf_method_parameter = s.read("uint:8")
        tx_nf_method_parameter = s.read("uint:8")
        return DllConfigFile(active_access_class=ac,
                             lq_filter=lq_filter,
                             nf_ctrl=nf_ctrl,
                             rx_nf_method_parameter=rx_nf_method_parameter,
                             tx_nf_method_parameter=tx_nf_method_parameter)

    def __iter__(self):
        yield self.active_access_class
        for byte in bytearray(struct.pack(">H", 0)):  # RFU
            yield byte
        yield self.lq_filter
        yield self.nf_ctrl
        yield self.rx_nf_method_parameter
        yield self.tx_nf_method_parameter

    def __str__(self):
        return "active_access_class={}, lq_filter={}, nf_ctrl={}, rx_nf_method_parameter, tx_nf_method_parameter".format(
            self.active_access_class, self.lq_filter, self.nf_ctrl,
            self.rx_nf_method_parameter, self.tx_nf_method_parameter)
class ForegroundFrameControl(Validatable):

  SCHEMA = [{
    "id_type": Types.ENUM(IdType),
    "eirp_index": Types.INTEGER(None, 0, 63)
  }]

  def __init__(self, id_type, eirp_index=0):
    self.id_type = id_type
    self.eirp_index = eirp_index
    super(ForegroundFrameControl, self).__init__()

  @staticmethod
  def parse(s):
    id_type = IdType(s.read("uint:2"))
    eirp_index = s.read("uint:6")
    return ForegroundFrameControl(
      id_type=id_type,
      eirp_index=eirp_index
    )

  def __iter__(self):
    byte = 0
    byte |= self.id_type.value << 6
    byte += self.eirp_index
    yield byte
Exemple #9
0
class Control(Validatable):

    SCHEMA = [{
        "has_network_layer_security": Types.BOOLEAN(),
        "has_multi_hop": Types.BOOLEAN(),
        "has_origin_access_id": Types.BOOLEAN(),
        "is_origin_access_id_vid": Types.BOOLEAN(),
        "origin_access_class": Types.INTEGER(min=0, max=15)
    }]

    def __init__(self, has_network_layer_security, has_multi_hop,
                 has_origin_access_id, is_origin_access_id_vid,
                 origin_access_class):
        self.has_network_layer_security = has_network_layer_security
        self.has_multi_hop = has_multi_hop
        self.has_origin_access_id = has_origin_access_id
        self.is_origin_access_id_vid = is_origin_access_id_vid
        self.origin_access_class = origin_access_class
        super(Control, self).__init__()

    def __iter__(self):
        byte = 0
        if self.has_network_layer_security: byte |= 1 << 7
        if self.has_multi_hop: byte |= 1 << 6
        if self.has_origin_access_id: byte |= 1 << 5
        if self.is_origin_access_id_vid: byte |= 1 << 4
        byte += self.origin_access_class
        yield byte
Exemple #10
0
class BackgroundFrameControl(Validatable):

  SCHEMA = [{
    "id_type": Types.ENUM(IdType),
    "tag": Types.INTEGER(None, 0, 63)
  }]

  def __init__(self, id_type, tag):
    self.id_type = id_type
    self.tag = tag
    super(BackgroundFrameControl, self).__init__()

  @staticmethod
  def parse(s):
    id_type = IdType(s.read("uint:2"))
    tag = s.read("uint:6")
    return BackgroundFrameControl(
      id_type=id_type,
      tag=tag
    )

  def __iter__(self):
    byte = 0
    byte |= self.id_type.value << 6
    byte += self.tag
    yield byte
Exemple #11
0
class ChannelID(Validatable):

    SCHEMA = [{
        "channel_header": Types.OBJECT(ChannelHeader),
        "channel_index": Types.INTEGER(min=0, max=0xFFFF),
    }]

    def __init__(self, channel_header, channel_index):
        self.channel_header = channel_header
        self.channel_index = channel_index
        super(ChannelID, self).__init__()

    def __iter__(self):
        for byte in self.channel_header:
            yield byte
        for byte in bytearray(struct.pack(">H", self.channel_index)):
            yield byte

    @staticmethod
    def parse(s):
        channel_header = ChannelHeader.parse(s)
        channel_index = s.read("uint:16")
        return ChannelID(channel_header=channel_header,
                         channel_index=channel_index)

    def __str__(self):
        return "{0}{1:0>3}".format(self.channel_header, self.channel_index)

    @staticmethod
    def from_string(s):
        channel_header = ChannelHeader.from_string(s[0:5])
        channel_index = int(s[5:8])
        return ChannelID(channel_header=channel_header,
                         channel_index=channel_index)
Exemple #12
0
class IndirectInterfaceOperand(Validatable):

    SCHEMA = [{
        "interface_file_id":
        Types.INTEGER(min=0x40, max=0xFF),
        "interface_configuration_overload":
        Types.OBJECT(Addressee, nullable=True)  # TODO assuming D7ASP interface
    }]

    def __init__(self,
                 interface_file_id,
                 interface_configuration_overload=None):
        self.interface_file_id = interface_file_id
        self.interface_configuration_overload = interface_configuration_overload
        super(IndirectInterfaceOperand, self).__init__()

    def __iter__(self):
        yield self.interface_file_id
        if self.interface_configuration_overload is not None:
            for byte in self.interface_configuration_overload:
                yield byte

    def __str__(self):
        return "interface-file-id={}, configuration-overload={}".format(
            self.interface_file_id, self.interface_configuration_overload)
class StatusAction(Action):
    SCHEMA = [{
        "status_operand_extension":
        Types.INTEGER(values=StatusActionOperandExtensions.ALL),
        "operation":
        Types.OBJECT(Operation),
        "operand":
        Types.OBJECT(nullable=True)  # there is no Operand base-class
    }]

    def __init__(self, status_operand_extension, operation):
        self.status_operand_extension = status_operand_extension
        self.operation = operation
        super(StatusAction, self).__init__(operation=operation)

    def __iter__(self):
        byte = 0
        byte |= self.status_operand_extension << 6
        byte += self.op
        yield byte

        for byte in self.operation:
            yield byte

    def __str__(self):
        return "{}".format(self.operand)
Exemple #14
0
class AccessProfileFile(File, Validatable):
    SCHEMA = [{
        "access_specifier": Types.INTEGER(min=0, max=14),
        "access_profile": Types.OBJECT(AccessProfile, nullable=True)
    }]

    def __init__(self, access_specifier=0, access_profile=None):
        self.access_specifier = access_specifier
        self.access_profile = access_profile
        Validatable.__init__(self)
        File.__init__(self,
                      SystemFileIds.ACCESS_PROFILE_0.value + access_specifier,
                      65)

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

    @staticmethod
    def parse(s):
        return AccessProfileFile(
            access_specifier=0,
            access_profile=AccessProfile.parse(s))  # TODO access_specifier?

    def __str__(self):
        return "active_specifier={}, access_profile={}".format(
            self.access_specifier, self.access_profile)
Exemple #15
0
class DllStatusFile(File, Validatable):
  SCHEMA = [{
    "last_rx_packet_level": Types.INTEGER(min=0, max=0xFF),
    "last_rx_packet_link_budget": Types.INTEGER(min=0, max=0xFF),
    "noise_floor": Types.INTEGER(min=0, max=0xFF),
    "channel_header": Types.OBJECT(ChannelHeader),
    "channel_index":Types.INTEGER(min=0, max=0xFFFF),
    "scan_timeout_ratio": Types.INTEGER(min=0, max=0xFFFF),
    "scan_count": Types.INTEGER(min=0, max=0xFFFFFFFF),
    "scan_timeout_count": Types.INTEGER(min=0, max=0xFFFFFFFF)
  }]

  def __init__(self, last_rx_packet_level=0, last_rx_packet_link_budget=0, noise_floor=0,
               channel_header=ChannelHeader(channel_coding=ChannelCoding.FEC_PN9, channel_band=ChannelBand.BAND_868, channel_class=ChannelClass.LO_RATE),
               channel_index=0, scan_timeout_ratio=0, scan_count=0, scan_timeout_count=0):
    self.last_rx_packet_level=last_rx_packet_level
    self.last_rx_packet_link_budget=last_rx_packet_link_budget
    self.noise_floor=noise_floor
    self.channel_header=channel_header
    self.channel_index=channel_index
    self.scan_timeout_ratio=scan_timeout_ratio
    self.scan_count=scan_count
    self.scan_timeout_count=scan_timeout_count
    File.__init__(self, SystemFileIds.DLL_STATUS.value, 16)
    Validatable.__init__(self)

  @staticmethod
  def parse(s):
    last_rx_packet_level = s.read("uint:8")
    last_rx_packet_link_budget = s.read("uint:8")
    noise_floor = s.read("uint:8")
    channel_header = ChannelHeader.parse(s)
    channel_index = s.read("uint:16")
    scan_timeout_ratio = s.read("uint:16")
    scan_count = s.read("uint:32")
    scan_timeout_count = s.read("uint:32")
    return DllStatusFile(last_rx_packet_level=last_rx_packet_level, last_rx_packet_link_budget=last_rx_packet_link_budget,
                         noise_floor=noise_floor, channel_header=channel_header, channel_index=channel_index,
                         scan_timeout_ratio=scan_timeout_ratio, scan_count=scan_count, scan_timeout_count=scan_timeout_count)

  def __iter__(self):
    yield self.last_rx_packet_level
    yield self.last_rx_packet_link_budget
    yield self.noise_floor
    for byte in self.channel_header:
      yield byte
    for byte in bytearray(struct.pack(">H", self.channel_index)):
      yield byte
    for byte in bytearray(struct.pack(">H", self.scan_timeout_ratio)):
      yield byte
    for byte in bytearray(struct.pack(">I", self.scan_count)):
      yield byte
    for byte in bytearray(struct.pack(">I", self.scan_timeout_count)):
      yield byte


  def __str__(self):
    return "last_rx_packet_level={}, last_rx_packet_link_budget={}, noise_floor={}, channel={}{}, scan_timeout_ratio={}, scan_count={}, scan_timeout_count={}".format(self.last_rx_packet_level, self.last_rx_packet_link_budget, self.noise_floor, self.channel_header, self.channel_index, self.scan_timeout_ratio, self.scan_count, self.scan_timeout_count)
Exemple #16
0
class Length(Validatable):

    SCHEMA = [{
        "length": Types.BITS(2),
        "value": Types.INTEGER(min=0, max=0x3FFFFFFF)
    }]

    def __init__(self, value=0):
        self.value = value
        super(Length, self).__init__()

    @staticmethod
    def parse(s):
        size = s.read("uint:2")  # + 1 = already read
        value = s.read("uint:" + str(6 + (size * 8)))
        return Length(value=value)

    def __iter__(self):
        byte = 0
        size = 1
        if self.value > 0x3F:
            size = 2
        if self.value > 0x3FFF:
            size = 3
        if self.value > 0x3FFFFF:
            size = 4

        byte += (size - 1) << 6

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

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

    def __str__(self):
        return str(self.value)

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.value == other.value
        elif isinstance(other, int):
            return self.value == other
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)
Exemple #17
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)
Exemple #18
0
class UidFile(File, Validatable):
    SCHEMA = [{"uid": Types.INTEGER(min=0, max=0xFFFFFFFFFFFFFFFF)}]

    def __init__(self, uid=0):
        self.uid = uid
        File.__init__(self, SystemFileIds.UID.value, 8)
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        uid = s.read("uint:64")
        return UidFile(uid=uid)

    def __iter__(self):
        for byte in bytearray(struct.pack(">Q", self.uid)):
            yield byte

    def __str__(self):
        return "uid={}".format(hex(self.uid))
Exemple #19
0
class Control(Validatable):

  SCHEMA = [{
    "is_target_address_set": Types.BOOLEAN(),
    "is_target_address_vid": Types.BOOLEAN(),
    "eirp_index": Types.INTEGER(None, 0, 63)
  }]

  def __init__(self, is_target_address_set, is_target_address_vid, eirp_index=0):
    self.is_target_address_set = is_target_address_set
    self.is_target_address_vid = is_target_address_vid
    self.eirp_index = eirp_index
    super(Control, self).__init__()

  def __iter__(self):
    byte = 0
    if self.is_target_address_set: byte |= 1 << 7
    if self.is_target_address_vid:  byte |= 1 << 6
    byte += self.eirp_index
    yield byte
Exemple #20
0
class ChannelStatusIdentifier(Validatable):
    # TODO update to D7AP v1.1

    SCHEMA = [{
        "channel_band": Types.ENUM(ChannelBand),
        "channel_bandwidth": Types.ENUM(Bandwidth),
        "channel_index": Types.INTEGER(min=0, max=1039)
    }]

    def __init__(self,
                 channel_band=ChannelBand.NOT_IMPL,
                 channel_bandwidth=Bandwidth.kHz25,
                 channel_index=0):
        self.channel_band = channel_band
        self.channel_bandwidth = channel_bandwidth
        self.channel_index = channel_index
        super(ChannelStatusIdentifier, self).__init__()

    def __iter__(self):
        byte = self.channel_band.value << 5
        byte += self.channel_bandwidth.value << 4
        byte += 0 << 3  # RFU
        byte += (self.channel_index >> 8) & 0x07
        yield byte
        yield self.channel_index & 0xFF

    @staticmethod
    def parse(s):
        channel_band = ChannelBand(s.read("uint:3"))
        channel_bandwidth = Bandwidth(s.read("uint:1"))
        s.read("uint:1")  # RFU
        channel_index = s.read("uint:11")
        return ChannelStatusIdentifier(channel_band=channel_band,
                                       channel_bandwidth=channel_bandwidth,
                                       channel_index=channel_index)

    def __str__(self):
        return "channel_band={}, channel_bandwidth={}, channel_index={}".format(
            self.channel_band.name.lstrip("BAND_"),
            self.channel_bandwidth.to_string(), self.channel_index)
Exemple #21
0
class Addressee(Validatable):

    # addressee ID length
    ID_LENGTH_BROADCAST = 0
    ID_LENGTH_VID = 2
    ID_LENGTH_UID = 8

    SCHEMA = [
        {
            # broadcast
            "id_type": Types.INTEGER([IdType.BCAST]),
            "access_class": Types.BITS(4),
            "id_length": Types.INTEGER([0]),
            "id": Types.INTEGER([None])
        },
        {
            # virtual
            "id_type": Types.INTEGER([IdType.VID]),
            "access_class": Types.BITS(4),
            "id_length": Types.INTEGER([2]),
            "id": Types.INTEGER(min=0, max=0xFFFF)
        },
        {
            # unicast
            "id_type": Types.INTEGER([IdType.UID]),
            "access_class": Types.BITS(4),
            "id_length": Types.INTEGER([8]),
            "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.BCAST, id=None):
        self.id_type = id_type
        self.access_class = access_class
        self.id = id
        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.BCAST: return Addressee.ID_LENGTH_BROADCAST
        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 = s.read("uint:2")
        cl = s.read("uint:4")
        l = Addressee.length_for(id_type)
        id = s.read("uint:" + str(l * 8)) if l > 0 else None
        return Addressee(id_type=id_type, access_class=cl, id=id)

    def __iter__(self):
        byte = 0
        # pad 2 << 7 << 6
        byte |= self.id_type << 4
        byte += self.access_class
        yield byte

        if self.id_length > 0:
            id = bytearray(struct.pack(">Q", self.id))[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, hex(self.id))
Exemple #22
0
class PhyStatusFile(File, Validatable):
    SCHEMA = [{
        "up_time":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "rx_time":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "tx_time":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "tx_duty_cycle":
        Types.INTEGER(min=0, max=1000),
        "channel_status_list_length":
        Types.INTEGER(min=0, max=0xFF),
        "channel_status_identifier":
        Types.LIST(ChannelStatusIdentifier, minlength=0, maxlength=0xFF),
        "channel_noise_floor":
        Types.LIST(minlength=0, maxlength=0xFF)
    }]

    def __init__(self,
                 up_time=0,
                 rx_time=0,
                 tx_time=0,
                 tx_duty_cycle=0,
                 channel_status_list_length=0,
                 channel_status_identifier=[],
                 channel_noise_floor=[]):
        self.up_time = up_time
        self.rx_time = rx_time
        self.tx_time = tx_time
        self.tx_duty_cycle = tx_duty_cycle
        self.channel_status_list_length = channel_status_list_length

        self.channel_status_identifier = channel_status_identifier
        if len(channel_status_identifier) != channel_status_list_length:
            self.channel_status_identifier.extend(
                [ChannelStatusIdentifier()] *
                (channel_status_list_length - len(channel_status_identifier)))

        self.channel_noise_floor = channel_noise_floor
        if len(channel_noise_floor) != channel_status_list_length:
            self.channel_noise_floor.extend(
                [0] * (channel_status_list_length - len(channel_noise_floor)))

        File.__init__(self, SystemFileIds.PHY_STATUS.value,
                      15 + (3 * 10))  # allocate enough space for 20 channels
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        up_time = s.read("uint:32")
        rx_time = s.read("uint:32")
        tx_time = s.read("uint:32")
        tx_duty_cycle = s.read("uint:16")
        channel_status_list_length = s.read("uint:8")
        channel_status_identifier = []
        channel_noise_floor = []
        for counter in range(channel_status_list_length):
            channel_status_identifier.append(
                ChannelStatusIdentifier().parse(s))
            channel_noise_floor.append(s.read("uint:8"))

        return PhyStatusFile(
            up_time=up_time,
            rx_time=rx_time,
            tx_time=tx_time,
            tx_duty_cycle=tx_duty_cycle,
            channel_status_list_length=channel_status_list_length,
            channel_status_identifier=channel_status_identifier,
            channel_noise_floor=channel_noise_floor)

    def __iter__(self):
        for byte in bytearray(struct.pack(">I", self.up_time)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.rx_time)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.tx_time)):
            yield byte
        for byte in bytearray(struct.pack(">H", self.tx_duty_cycle)):
            yield byte
        yield self.channel_status_list_length
        for counter in range(self.channel_status_list_length):
            for byte in self.channel_status_identifier[counter]:
                yield byte
            yield self.channel_noise_floor[counter]

    def __str__(self):
        channel_status = ""
        for counter in range(self.channel_status_list_length):
            channel_status = channel_status + "identifier={}, noise_floor={}; ".format(
                str(self.channel_status_identifier[counter]),
                self.channel_noise_floor[counter])
        channel_status = "[{}]".format(channel_status[:-2])

        return "up_time={}, rx_time={}, tx_time={}, tx_duty_cycle={}, channel_status_list_length={}, list={}".format(
            self.up_time, self.rx_time, self.tx_time, self.tx_duty_cycle,
            self.channel_status_list_length, channel_status)
Exemple #23
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)
Exemple #24
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
        )
Exemple #25
0
class FactorySettingsFile(File, Validatable):

    SCHEMA = [{
        "gain":
        Types.INTEGER(min=-128, max=127),
        "rx_bw_low_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "rx_bw_normal_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "rx_bw_high_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "bitrate_lo_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "fdev_lo_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "bitrate_normal_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "fdev_normal_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "bitrate_hi_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "fdev_hi_rate":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "preamble_size_lo_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_size_normal_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_size_hi_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_detector_size_lo_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_detector_size_normal_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_detector_size_hi_rate":
        Types.INTEGER(min=0, max=255),
        "preamble_tol":
        Types.INTEGER(min=0, max=255),
        "rssi_smoothing":
        Types.INTEGER(min=0, max=255),
        "rssi_offset":
        Types.INTEGER(min=-126, max=125),
        "lora_bw":
        Types.INTEGER(min=0, max=0xFFFFFFFF),
        "lora_SF":
        Types.INTEGER(min=6, max=12),
        "gaussian":
        Types.INTEGER(min=0, max=3),
        "paramp":
        Types.INTEGER(min=0, max=0xFFFF)
    }]

    def __init__(self,
                 gain=0,
                 rx_bw_low_rate=10468,
                 rx_bw_normal_rate=78646,
                 rx_bw_high_rate=125868,
                 bitrate_lo_rate=9600,
                 fdev_lo_rate=4800,
                 bitrate_normal_rate=55555,
                 fdev_normal_rate=50000,
                 bitrate_hi_rate=166667,
                 fdev_hi_rate=41667,
                 preamble_size_lo_rate=5,
                 preamble_size_normal_rate=5,
                 preamble_size_hi_rate=7,
                 preamble_detector_size_lo_rate=3,
                 preamble_detector_size_normal_rate=3,
                 preamble_detector_size_hi_rate=3,
                 preamble_tol_lo_rate=15,
                 preamble_tol_normal_rate=10,
                 preamble_tol_hi_rate=10,
                 rssi_smoothing=8,
                 rssi_offset=0,
                 lora_bw=125000,
                 lora_SF=9,
                 gaussian=2,
                 paramp=40):
        self.gain = gain
        self.rx_bw_low_rate = rx_bw_low_rate
        self.rx_bw_normal_rate = rx_bw_normal_rate
        self.rx_bw_high_rate = rx_bw_high_rate
        self.bitrate_lo_rate = bitrate_lo_rate
        self.fdev_lo_rate = fdev_lo_rate
        self.bitrate_normal_rate = bitrate_normal_rate
        self.fdev_normal_rate = fdev_normal_rate
        self.bitrate_hi_rate = bitrate_hi_rate
        self.fdev_hi_rate = fdev_hi_rate
        self.preamble_size_lo_rate = preamble_size_lo_rate
        self.preamble_size_normal_rate = preamble_size_normal_rate
        self.preamble_size_hi_rate = preamble_size_hi_rate
        self.preamble_detector_size_lo_rate = preamble_detector_size_lo_rate
        self.preamble_detector_size_normal_rate = preamble_detector_size_normal_rate
        self.preamble_detector_size_hi_rate = preamble_detector_size_hi_rate
        self.preamble_tol_lo_rate = preamble_tol_lo_rate
        self.preamble_tol_normal_rate = preamble_tol_normal_rate
        self.preamble_tol_hi_rate = preamble_tol_hi_rate
        self.rssi_smoothing = int(ceil(log(rssi_smoothing, 2))) - 1
        self.rssi_offset = rssi_offset
        self.lora_bw = lora_bw
        self.lora_SF = lora_SF
        self.gaussian = gaussian
        self.paramp = paramp
        File.__init__(self, SystemFileIds.FACTORY_SETTINGS.value, 56)
        Validatable.__init__(self)

    @staticmethod
    def parse(s):
        gain = s.read("int:8")
        rx_bw_low_rate = s.read("uint:32")
        rx_bw_normal_rate = s.read("uint:32")
        rx_bw_high_rate = s.read("uint:32")
        bitrate_lo_rate = s.read("uint:32")
        fdev_lo_rate = s.read("uint:32")
        bitrate_normal_rate = s.read("uint:32")
        fdev_normal_rate = s.read("uint:32")
        bitrate_hi_rate = s.read("uint:32")
        fdev_hi_rate = s.read("uint:32")

        preamble_size_lo_rate = s.read("uint:8")
        preamble_size_normal_rate = s.read("uint:8")
        preamble_size_hi_rate = s.read("uint:8")

        preamble_detector_size_lo_rate = s.read("uint:8")
        preamble_detector_size_normal_rate = s.read("uint:8")
        preamble_detector_size_hi_rate = s.read("uint:8")
        preamble_tol_lo_rate = s.read("uint:8")
        preamble_tol_normal_rate = s.read("uint:8")
        preamble_tol_hi_rate = s.read("uint:8")

        rssi_smoothing = s.read("uint:8")
        rssi_offset = s.read("uint:8")

        lora_bw = s.read("uint:32")
        lora_SF = s.read("uint:8")

        gaussian = s.read("uint:8")
        paramp = s.read("uint:16")

        return FactorySettingsFile(
            gain=gain,
            rx_bw_low_rate=rx_bw_low_rate,
            rx_bw_normal_rate=rx_bw_normal_rate,
            rx_bw_high_rate=rx_bw_high_rate,
            bitrate_lo_rate=bitrate_lo_rate,
            fdev_lo_rate=fdev_lo_rate,
            bitrate_normal_rate=bitrate_normal_rate,
            fdev_normal_rate=fdev_normal_rate,
            bitrate_hi_rate=bitrate_hi_rate,
            fdev_hi_rate=fdev_hi_rate,
            preamble_size_lo_rate=preamble_size_lo_rate,
            preamble_size_normal_rate=preamble_size_normal_rate,
            preamble_size_hi_rate=preamble_size_hi_rate,
            preamble_detector_size_lo_rate=preamble_detector_size_lo_rate,
            preamble_detector_size_normal_rate=
            preamble_detector_size_normal_rate,
            preamble_detector_size_hi_rate=preamble_detector_size_hi_rate,
            preamble_tol_lo_rate=preamble_tol_lo_rate,
            preamble_tol_normal_rate=preamble_tol_normal_rate,
            preamble_tol_hi_rate=preamble_tol_hi_rate,
            rssi_smoothing=rssi_smoothing,
            rssi_offset=rssi_offset,
            lora_bw=lora_bw,
            lora_SF=lora_SF,
            gaussian=gaussian,
            paramp=paramp)

    def __iter__(self):
        yield self.gain
        for byte in bytearray(struct.pack(">I", self.rx_bw_low_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.rx_bw_normal_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.rx_bw_high_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.bitrate_lo_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.fdev_lo_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.bitrate_normal_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.fdev_normal_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.bitrate_hi_rate)):
            yield byte
        for byte in bytearray(struct.pack(">I", self.fdev_hi_rate)):
            yield byte
        yield self.preamble_size_lo_rate
        yield self.preamble_size_normal_rate
        yield self.preamble_size_hi_rate
        yield self.preamble_detector_size_lo_rate
        yield self.preamble_detector_size_normal_rate
        yield self.preamble_detector_size_hi_rate
        yield self.preamble_tol_lo_rate
        yield self.preamble_tol_normal_rate
        yield self.preamble_tol_hi_rate
        yield self.rssi_smoothing
        yield self.rssi_offset
        for byte in bytearray(struct.pack(">I", self.lora_bw)):
            yield byte
        yield self.lora_SF
        yield self.gaussian
        for byte in bytearray(struct.pack(">H", self.paramp)):
            yield byte

    def __str__(self):
        return "gain={}, rx_bw_low_rate={}, rx_bw_normal_rate={}, rx_bw_high_rate={}, low rate={} : {}, normal rate={} : {}, high rate={} : {}, preamble sizes {} : {} : {}, preamble detector size {} : {} : {} with tol {} : {} : {}, rssi smoothing {} with offset {}\nlora sf set to {}, bw to {}\ngaussian set to {} and paramp to {} microseconds".format(
            self.gain, self.rx_bw_low_rate, self.rx_bw_normal_rate,
            self.rx_bw_high_rate, self.bitrate_lo_rate, self.fdev_lo_rate,
            self.bitrate_normal_rate, self.fdev_normal_rate,
            self.bitrate_hi_rate, self.fdev_hi_rate,
            self.preamble_size_lo_rate, self.preamble_size_normal_rate,
            self.preamble_size_hi_rate, self.preamble_detector_size_lo_rate,
            self.preamble_detector_size_normal_rate,
            self.preamble_detector_size_hi_rate, self.preamble_tol_lo_rate,
            self.preamble_tol_normal_rate, self.preamble_tol_hi_rate,
            self.rssi_smoothing, self.rssi_offset, self.lora_bw, self.lora_SF,
            self.gaussian, self.paramp)
Exemple #26
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
        )
Exemple #27
0
class Frame(Validatable):

    SCHEMA = [{
        "control": Types.OBJECT(Control),
        "dialog_id": Types.INTEGER(min=0, max=255),
        "transaction_id": Types.INTEGER(min=0, max=255),
        "agc_rx_level_i": Types.INTEGER(min=0, max=31),
        "tl": Types.OBJECT(CT, nullable=True),
        "te": Types.OBJECT(CT, nullable=True),
        "tc": Types.OBJECT(CT, nullable=True),
        "ack_template": Types.OBJECT(nullable=True),  # TODO
        "alp_command": Types.OBJECT(Command)
    }]

    def __init__(self,
                 control,
                 dialog_id,
                 transaction_id,
                 alp_command,
                 agc_rx_level_i=10,
                 tl=None,
                 te=None,
                 tc=None,
                 ack_template=None):
        if agc_rx_level_i == None:
            agc_rx_level_i = 10

        self.control = control
        self.dialog_id = dialog_id
        self.transaction_id = transaction_id
        self.agc_rx_level_i = agc_rx_level_i
        self.tl = tl
        self.te = te
        self.tc = tc
        self.ack_template = ack_template
        self.alp_command = alp_command
        super(Frame, self).__init__()

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

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

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

        target_rx_level_i = None
        if control.has_agc:
            target_rx_level_i = bitstream.read("uint:8")
            payload_length -= 1

        tl = None
        if control.has_tl:
            tl = CT.parse(bitstream)
            payload_length -= 1

        te = None
        if control.has_te:
            te = CT.parse(bitstream)
            payload_length -= 1

        tc = None
        # TODO currently we have no way to know if Tc is present or not
        # Tc is present when control.is_ack_requested AND when we are requester,
        # while responders copy this flag but do NOT provide a Tc.
        # When parsing single frames without knowledge of dialogs we cannot determine this.
        # We use control.is_dialog_start for now but this will break when we start supporting multiple transactions per dialog
        if control.is_ack_requested and control.is_dialog_start:
            tc = CT.parse(bitstream)
            payload_length -= 1

        ack_template = None
        if control.is_ack_not_void:
            transaction_id_start = bitstream.read("uint:8")
            payload_length = payload_length - 1
            transaction_id_stop = bitstream.read("uint:8")
            payload_length = payload_length - 1
            assert transaction_id_start == transaction_id, "Other case not implemented yet"
            assert transaction_id_stop == transaction_id, "Other case not implemented yet"
            # TODO ack bitmap (for when transaction_id_start != transaction_id)
            ack_template = [transaction_id_start, transaction_id_stop]

        assert control.is_ack_record_requested == False, "Not implemented yet"
        assert control.is_ack_not_void == False, "Not implemented yet"

        alp_command = AlpParser().parse(bitstream, payload_length)

        return Frame(control=control,
                     dialog_id=dialog_id,
                     transaction_id=transaction_id,
                     agc_rx_level_i=target_rx_level_i,
                     tl=tl,
                     te=te,
                     tc=tc,
                     ack_template=ack_template,
                     alp_command=alp_command)

    def __iter__(self):
        for byte in self.control:
            yield byte
        yield self.dialog_id
        yield self.transaction_id
        if self.control.has_agc:
            yield self.agc_rx_level_i

        if self.control.has_tl:
            yield self.tl

        if self.control.has_te:
            yield self.te

        if self.control.is_ack_not_void:
            for byte in self.ack_template:
                yield byte

        for byte in self.alp_command:
            yield byte