def tobytes(self): bits = bitarray() # build header bits += int_to_bitarray((self.size / 24) - 1, 2) # (0-1): packet length bits += int_to_bitarray(self.index, 2) # (2-3): continuity index bits += bitarray('1' if self.first else '0') # (4): first packet of datagroup series bits += bitarray( '1' if self.last else '0') # (5): last packet of datagroup series bits += int_to_bitarray(self.address, 10) # (6-15): packet address bits += bitarray('0') # (16): Command flag = 0 (data) bits += int_to_bitarray(len(self.data), 7) # (17-23): useful data length # add the packet data tmp = bitarray() tmp.frombytes(self.data) bits += tmp # (24-n): packet data # add packet padding if needed bits += bitarray('0' * (self.size - len(self.data) - 5) * 8) # add CRC bits += int_to_bitarray(calculate_crc(bits.tobytes()), 16) return bits.tobytes()
def _segment(data, strategy): segments = [] # partition the segments up using the maximum segment size i = 0 if not data: return segments while i < len(data): segment_size = strategy.get_next_segment_size(data, i, segments) # get segment data segment_data = data[i:i + segment_size if i + segment_size < len(data) else len(data)] # segment header bits = bitarray() bits += int_to_bitarray( 0, 3) # (0-2): Repetition Count remaining (0 = only broadcast) bits += int_to_bitarray(len(segment_data), 13) # (3-16): SegmentSize segments.append(bits.tobytes() + segment_data) i += segment_size return segments
def encode_data(self): bits = bitarray() bits += int_to_bitarray(self.charset, 4) # (0-3): Character set indicator bits += int_to_bitarray(0, 4) # (4-7): RFA tmp = bitarray() tmp.fromstring(self.url) bits += tmp return bits
def tobytes(self): bits = bitarray() # datagroup header bits += bitarray('0') # (0): ExtensionFlag - 0=no extension bits += bitarray( '1' if self.crc_enabled else '0' ) # (1): CrcFlag - true if there is a CRC at the end of the datagroup bits += bitarray('1') # (2): SegmentFlag - 1=segment header included bits += bitarray('1') # (3): UserAccessFlag - true bits += int_to_bitarray(self._type, 4) # (4-7): DataGroupType bits += int_to_bitarray(self.continuity % 16, 4) # (8-11): ContinuityIndex bits += int_to_bitarray( self.repetition, 4) # (12-15): RepetitionIndex - remaining = 0 (only this once) # session header # segment field bits += bitarray( '1' if self.last else '0') # (16): Last - true if the last segment bits += int_to_bitarray(self.segment_index, 15) # (17-32): SegmentNumber # user access field bits += bitarray('000') # (33-35): RFA bits += bitarray( '1') # (36): TransportId - true to include Transport ID bits += int_to_bitarray( 2, 4 ) # (37-40): LengthIndicator - length of transport Id and End user address fields (will be 2 bytes as only transport ID defined) bits += int_to_bitarray(self._transport_id, 16) # (41-56) transport ID # data field tmp = bitarray() tmp.frombytes(self._data) bits += tmp # CRC crc = 0 if self.crc_enabled: crc = calculate_crc(bits.tobytes()) bits += int_to_bitarray(crc, 16) return bits.tobytes()
def encode_directorymode(objects, directory_parameters=None, segmenting_strategy=None): """ Encode a set of MOT objects into directory mode segments, along with a segmented directory object """ datagroups = [] if not segmenting_strategy: segmenting_strategy = ConstantSegmentSize() # build the directory entries entries = bitarray() for object in objects: # encode header extension parameters extension_bits = bitarray() for parameter in object.get_parameters(): extension_bits += parameter.encode() # transport ID in first 2 bytes entries += int_to_bitarray(object.get_transport_id(), 16) # add the core parameters into the header entries += int_to_bitarray(len(object.get_body()), 28) # (0-27): BodySize in bytes entries += int_to_bitarray( extension_bits.length() / 8 + 7, 13) # (28-40): HeaderSize in bytes (core=7 + extension) entries += int_to_bitarray(object.get_type().type, 6) # (41-46): ContentType entries += int_to_bitarray(object.get_type().subtype, 9) # (47-55): ContentSubType entries += extension_bits # (56-n): Header extension data # build directory parameters directory_params = bitarray() if directory_parameters is not None: for parameter in directory_parameters: directory_params += parameter.encode() # build directory header bits = bitarray() bits += bitarray('0') # (0): CompressionFlag: This bit shall be set to 0 bits += bitarray('0') # (1): RFU bits += int_to_bitarray( len(entries.tobytes()), 30) # (2-31): DirectorySize: total size of the MOT directory in bytes bits += int_to_bitarray( len(objects), 16 ) # (32-47): NumberOfObjects: Total number of objects described by the directory bits += int_to_bitarray( 0, 24 ) # (48-71): DataCarouselPeriod: Max time in tenths of seconds for the data carousel to complete a cycle. Value of zero for undefined bits += bitarray('000') # (72-74): RFU bits += int_to_bitarray( 0, 13 ) # (75-87): SegmentSize: Size in bytes that will be used for the segmentation of objects within the MOT carousel. Value of zero indicates that objects can have different segmentation sizes. The last segment of an obect may be smaller than this size. bits += int_to_bitarray( len(directory_params.tobytes()), 16 ) # (88-103): DirectoryExtensionLength: Length of following directory extension bytes # add directory parameters bits += directory_params # add directory entries bits += entries # segment and add directory datagroups with a new transport ID directory_transport_id = generate_transport_id() segments = _segment(bits.tobytes(), segmenting_strategy) for i, segment in enumerate(segments): header_group = Datagroup(directory_transport_id, DIRECTORY_UNCOMPRESSED, segment, i, i % 16, last=True if i == len(segments) - 1 else False) tmp = bitarray() tmp.frombytes(header_group.tobytes()) tmp.frombytes(header_group.tobytes()) datagroups.append(header_group) # add body datagroups for object in objects: segments = _segment(object.get_body(), segmenting_strategy) for i, segment in enumerate(segments): body_group = Datagroup(object.get_transport_id(), BODY, segment, i, i % 16, last=True if i == len(segments) - 1 else False) datagroups.append(body_group) return datagroups
def encode_headermode(objects, segmenting_strategy=None): """ Encode a set of MOT Objects into header mode segments """ datagroups = [] if not segmenting_strategy: segmenting_strategy = ConstantSegmentSize() # backward compatibility if not isinstance(objects, list): objects = [objects] logger.debug('encoding %d MOT objects to header mode datagroups', len(objects)) for object in objects: if not object: raise ValueError('object returned is null') # split body data into segments body_data = object.get_body() body_segments = _segment(body_data, segmenting_strategy) # encode header extension parameters extension_bits = bitarray() for parameter in object.get_parameters(): extension_bits += parameter.encode() # insert the core parameters into the header bits = bitarray() bits += int_to_bitarray(len(body_data) if body_data else 0, 28) # (0-27): BodySize in bytes bits += int_to_bitarray( extension_bits.length() / 8 + 7, 13) # (28-40): HeaderSize in bytes (core=7 + extension) bits += int_to_bitarray(object.get_type().type, 6) # (41-46): ContentType bits += int_to_bitarray(object.get_type().subtype, 9) # (47-55): ContentSubType bits += extension_bits # (56-n): Header extension data header_segments = _segment(bits.tobytes(), segmenting_strategy) # add header datagroups for i, segment in enumerate(header_segments): header_group = Datagroup(object.get_transport_id(), HEADER, segment, i, i % 16, last=True if i == len(header_segments) - 1 else False) datagroups.append(header_group) # add body datagroups for i, segment in enumerate(body_segments): body_group = Datagroup(object.get_transport_id(), BODY, segment, i, i % 16, last=True if i == len(body_segments) - 1 else False) datagroups.append(body_group) return datagroups