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 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 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 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 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 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 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 def __str__(self): return "act_enabled={}, act_condition={}, storage_class={}".format( self.act_enabled, self.act_condition, self.storage_class) def __eq__(self, other): if isinstance(other, FileProperties): return self.__dict__ == other.__dict__ return False def __ne__(self, other): return not self.__eq__(other)
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)
class QoS(Validatable): SCHEMA = [{ "stop_on_err": Types.BOOLEAN(), "record": Types.BOOLEAN(), "resp_mod": Types.ENUM(ResponseMode), "retry_mod": Types.ENUM(RetryMode) }] def __init__(self, resp_mod=ResponseMode.RESP_MODE_NO, retry_mod=RetryMode.RETRY_MODE_NO, stop_on_err=False, record=False): self.resp_mod = resp_mod self.retry_mod = retry_mod self.stop_on_err = stop_on_err self.record = record super(QoS, self).__init__() def __iter__(self): byte = 0 if self.stop_on_err: byte |= 1 << 7 if self.record: byte |= 1 << 6 byte |= self.retry_mod.value << 3 byte += self.resp_mod.value yield byte @staticmethod def parse(s): stop_on_error = s.read("bool") record = s.read("bool") retry_mode = RetryMode(int(s.read("uint:3"))) resp_mode = ResponseMode(int(s.read("uint:3"))) return QoS(stop_on_err=stop_on_error, record=record, resp_mod=resp_mode, retry_mod=retry_mode) def __str__(self): return str(self.as_dict())
class Control(Validatable): SCHEMA = [{ "has_no_origin_access_id": Types.BOOLEAN(), "has_hopping": Types.BOOLEAN(), "origin_id_type": Types.ENUM( IdType, allowedvalues=[IdType.UID, IdType.VID, IdType.NOID, IdType.NBID]), "nls_method": Types.ENUM(NlsMethod), }] def __init__(self, has_no_origin_access_id, has_hopping, nls_method, origin_id_type): self.has_no_origin_access_id = has_no_origin_access_id self.nls_method = nls_method self.has_hopping = has_hopping self.origin_id_type = origin_id_type super(Control, self).__init__() @staticmethod def parse(bitstream): return Control( has_no_origin_access_id=bitstream.read("bool"), has_hopping=bitstream.read("bool"), origin_id_type=IdType(bitstream.read("uint:2")), nls_method=NlsMethod(bitstream.read("uint:4")), ) def __iter__(self): byte = 0 if self.has_no_origin_access_id: byte |= 1 << 7 if self.has_multi_hop: byte |= 1 << 6 if self.origin_id_type: byte |= 1 << 4 byte += self.nls_method yield byte
class QueryOperand(Validatable): SCHEMA = [{ "type": Types.ENUM(type=QueryType), "mask_present": Types.BOOLEAN(), "params": Types.OBJECT(ArithQueryParams), # TODO other query types "compare_length": Types.OBJECT(Length), "compare_value": Types.BYTES(), "file_a_offset": Types.OBJECT(Offset) }] def __init__(self, type, mask_present, params, compare_length, compare_value, file_a_offset): self.type = type self.mask_present = mask_present self.params = params self.compare_length = compare_length self.compare_value = compare_value self.file_a_offset = file_a_offset super(QueryOperand, self).__init__() def __iter__(self): byte = self.type.value << 5 byte += self.mask_present << 4 byte += bytearray(self.params)[0] yield byte for byte in self.compare_length: yield byte for byte in self.compare_value: yield byte for byte in self.file_a_offset: yield byte @staticmethod def parse(s): type = QueryType(s.read("uint:3")) assert (type == QueryType.ARITH_COMP_WITH_VALUE ) # TODO implement other types mask_present = s.read("bool") assert (mask_present is False) # TODO implement this params = ArithQueryParams.parse(s) compare_length = Length.parse(s) compare_value = map(ord, s.read("bytes:" + str(compare_length.value))) file_a_offset = Offset.parse(s) return QueryOperand(type=type, mask_present=mask_present, params=params, compare_length=compare_length, compare_value=compare_value, file_a_offset=file_a_offset)
class InterfaceConfiguration(Validatable): SCHEMA = [{ "interface_id": Types.ENUM(InterfaceType), "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.value for byte in self.interface_configuration: yield byte def __str__(self): return "interface-id={}, configuration={}".format( self.interface_id, self.interface_configuration)
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)