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())
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)
class IndirectForwardAction(Action): SCHEMA = [{ "overload": Types.BOOLEAN(), "resp": Types.BOOLEAN(), "op": Types.BITS(6), "operation": Types.OBJECT(IndirectForward), "operand": Types.OBJECT(IndirectInterfaceOperand ) # TODO for now only D7 interface is supported }] def __init__(self, overload=False, resp=False, operation=NoOperation()): self.overload = overload self.resp = resp super(IndirectForwardAction, self).__init__(operation) def __iter__(self): byte = 0 if self.overload: byte |= 1 << 7 if self.resp: byte |= 1 << 6 byte += self.op yield byte for byte in self.operation: yield byte
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
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
class Configuration(Validatable): SCHEMA = [{ "qos": Types.OBJECT(QoS), "dorm_to": Types.OBJECT(CT), "addressee": Types.OBJECT(Addressee) }] def __init__(self, qos=QoS(), dorm_to=CT(), addressee=Addressee()): self.qos = qos self.dorm_to = dorm_to self.addressee = addressee super(Configuration, self).__init__() def __iter__(self): for byte in self.qos: yield byte for byte in self.dorm_to: yield byte for byte in self.addressee: yield byte def __str__(self): return str(self.as_dict()) @staticmethod def parse(s): qos = QoS.parse(s) dorm_to = CT.parse(s) addressee = Addressee.parse(s) return Configuration(qos=qos, dorm_to=dorm_to, addressee=addressee)
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
class Action(Validatable): SCHEMA = [{ "op": Types.BITS(6), "operation": Types.OBJECT(Operation), "operand": Types.OBJECT(nullable=True) # there is no Operand base-class }] def __init__(self, operation=NoOperation()): self.operation = operation super(Action, self).__init__() @property def op(self): return self.operation.op @property def operand(self): return self.operation.operand def __str__(self): output = "op={}, operand={}({})".format( type(self.operation).__name__, type(self.operand).__name__, self.operand) return output
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 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)
class Action(Validatable): SCHEMA = [{ "op": Types.BITS(6), "operation": Types.OBJECT(Operation), "operand": Types.OBJECT(nullable=True) # there is no Operand base-class }] def __init__(self, operation=NoOperation()): self.operation = operation super(Action, self).__init__() @property def op(self): return self.operation.op @property def operand(self): return self.operation.operand def __str__(self): if isinstance(self.operation, ReturnFileData): # when reading a known system files we output the parsed data if self.operation.systemfile_type != None and self.operation.file_data_parsed != None: return "Received {} content: {}".format( self.operation.systemfile_type.__class__.__name__, self.operation.file_data_parsed) return str(self.operation)
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)
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)
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)
class ChannelHeader(Validatable): # TODO SCHEMA = [{ "channel_coding": Types.ENUM(ChannelCoding), "channel_class": Types.ENUM(ChannelClass), "channel_band": Types.ENUM(ChannelBand) }] def __init__(self, channel_coding, channel_class, channel_band): self.channel_coding = channel_coding self.channel_class = channel_class self.channel_band = channel_band super(ChannelHeader, self).__init__() def __iter__(self): byte = self.channel_band.value << 4 byte += self.channel_class.value << 2 byte += self.channel_coding.value yield byte @staticmethod def parse(s): s.read("uint:1") # RFU channel_band = ChannelBand(s.read("uint:3")) channel_class = ChannelClass(s.read("uint:2")) channel_coding = ChannelCoding(s.read("uint:2")) return ChannelHeader(channel_coding=channel_coding, channel_class=channel_class, channel_band=channel_band) def __str__(self): return "coding={}, class={}, band={}".format(self.channel_coding, self.channel_class, self.channel_band)
class Frame(Validatable): SCHEMA = [{ "timeout": Types.OBJECT(CT), "control": Types.OBJECT(Control), "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, timeout, control, origin_access_id, d7atp_frame): self.timeout = timeout self.control = control self.origin_access_id = origin_access_id self.d7atp_frame = d7atp_frame # TODO super(Frame, self).__init__() def __iter__(self): for byte in self.timeout: yield byte for byte in self.control: yield byte for byte in self.origin_access_id: yield byte for byte in self.d7atp_frame: yield byte
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)
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)
class FileProperties(Validatable): SCHEMA = [{ "act_enabled": Types.BOOLEAN(), "act_cond": Types.ENUM(ActionCondition), "storage_class": Types.ENUM(StorageClass) }] def __init__(self, act_enabled, act_condition, storage_class): self.act_enabled = act_enabled self.act_condition = act_condition self.storage_class = storage_class Validatable.__init__(self) @staticmethod def parse(s): act_enabled = s.read("bool") act_condition = ActionCondition(s.read("uint:3")) _rfu = s.read("uint:2") storage_class = StorageClass(s.read("uint:2")) return FileProperties(act_enabled, act_condition, storage_class) def __iter__(self): byte = 0 if self.act_enabled: byte += 1 << 7 byte += self.act_condition.value << 4 byte += self.storage_class.value yield byte
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
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)
class ChannelHeader(Validatable): # TODO SCHEMA = [{ "channel_coding": Types.ENUM(ChannelCoding), "channel_class": Types.ENUM(ChannelClass), "channel_band": Types.ENUM(ChannelBand) }] def __init__(self, channel_coding, channel_class, channel_band): self.channel_coding = channel_coding self.channel_class = channel_class self.channel_band = channel_band super(ChannelHeader, self).__init__() def __iter__(self): byte = self.channel_band.value << 4 byte += self.channel_class.value << 2 byte += self.channel_coding.value yield byte @staticmethod def parse(s): s.read("uint:1") # RFU channel_band = ChannelBand(s.read("uint:3")) channel_class = ChannelClass(s.read("uint:2")) channel_coding = ChannelCoding(s.read("uint:2")) return ChannelHeader(channel_coding=channel_coding, channel_class=channel_class, channel_band=channel_band) def __str__(self): band = self.channel_band.name.lstrip("BAND_") cl = self.channel_class.to_char() coding = self.channel_coding.to_char() return "{0}{1}{2}".format(band, cl, coding) @staticmethod def from_string(s): channel_band = ChannelBand.from_string(s[0:3]) channel_class = ChannelClass.from_char(s[3]) channel_coding = ChannelCoding.from_char(s[4]) return ChannelHeader(channel_band=channel_band, channel_class=channel_class, channel_coding=channel_coding) def __eq__(self, other): if type(other) is type(self): return self.__dict__ == other.__dict__ return False def __ne__(self, other): if isinstance(other, self.__class__): return not self.__eq__(other) return False
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)
class AccessProfile(Validatable): NUMBER_OF_SUB_PROFILES = 4 MAX_NUMBER_OF_SUB_BANDS = 8 # TODO update to D7AP v1.1 SCHEMA = [{ "channel_header": Types.OBJECT(ChannelHeader), "sub_profiles": Types.LIST(SubProfile, minlength=4, maxlength=4), "sub_bands": Types.LIST(SubBand, minlength=0, maxlength=8) }] def __init__(self, channel_header, sub_profiles, sub_bands): self.channel_header = channel_header self.sub_profiles = sub_profiles self.sub_bands = sub_bands super(AccessProfile, self).__init__() @staticmethod def parse(s): channel_header = ChannelHeader.parse(s) sub_profiles = [] for _ in range(AccessProfile.NUMBER_OF_SUB_PROFILES): sub_profiles.append(SubProfile.parse(s)) sub_bands = [] for _ in range(AccessProfile.MAX_NUMBER_OF_SUB_BANDS): sub_bands.append(SubBand.parse(s)) return AccessProfile(channel_header=channel_header, sub_bands=sub_bands, sub_profiles=sub_profiles) def __iter__(self): for byte in self.channel_header: yield byte for sp in self.sub_profiles: for byte in sp: yield byte for sb in self.sub_bands: for byte in sb: yield byte def __str__(self): subprofiles_string = "" for subprofile in self.sub_profiles: subprofiles_string = subprofiles_string + str(subprofile) subbands_string = "" for subband in self.sub_bands: subbands_string = subbands_string + str(subband) return "channel_header={}, sub_profiles={}, sub_bands={}".format( self.channel_header, subprofiles_string, subbands_string)
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)
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())
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 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)
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