def prepare_modulation_dialog(self) -> (ModulatorDialog, Message): preselected_index = self.ui.cBoxModulations.currentIndex() min_row, max_row, start, end = self.ui.tableMessages.selection_range() if min_row > -1: try: selected_message = self.table_model.protocol.messages[min_row] preselected_index = selected_message.modulator_index except IndexError: selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0], 0, [], MessageType("empty")) else: selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0], 0, [], MessageType("empty")) if len(self.table_model.protocol.messages) > 0: selected_message.bit_len = self.table_model.protocol.messages[0].bit_len for m in self.modulators: m.default_sample_rate = self.project_manager.device_conf["sample_rate"] modulator_dialog = ModulatorDialog(self.modulators, tree_model=self.tree_model, parent=self.parent()) modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex(preselected_index) modulator_dialog.finished.connect(self.refresh_modulators) modulator_dialog.finished.connect(self.refresh_pause_list) return modulator_dialog, selected_message
def setUp(self): self.field_types = FieldType.default_field_types() self.preamble_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.PREAMBLE) self.sync_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.SYNC) self.length_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.LENGTH) self.sequence_number_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.SEQUENCE_NUMBER) self.dst_address_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.DST_ADDRESS) self.src_address_field_type = self.__field_type_with_function(self.field_types, FieldType.Function.SRC_ADDRESS) self.protocol = ProtocolAnalyzer(None) with open(get_path_for_data_file("awre_consistent_addresses.txt")) as f: for line in f: self.protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", ""))) self.protocol.messages[-1].message_type = self.protocol.default_message_type # Assign participants alice = Participant("Alice", "A") bob = Participant("Bob", "B") alice_indices = {1, 2, 5, 6, 9, 10, 13, 14, 17, 18, 20, 22, 23, 26, 27, 30, 31, 34, 35, 38, 39, 41} for i, message in enumerate(self.protocol.messages): message.participant = alice if i in alice_indices else bob self.participants = [alice, bob] self.zero_crc_protocol = ProtocolAnalyzer(None) with open(get_path_for_data_file("awre_zeroed_crc.txt")) as f: for line in f: self.zero_crc_protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", ""))) self.zero_crc_protocol.messages[-1].message_type = self.protocol.default_message_type for i, message in enumerate(self.zero_crc_protocol.messages): message.participant = alice if i in alice_indices else bob
def __init__(self, destination: Participant, plain_bits, pause: int, message_type: MessageType, decoder=None, source=None, timestamp=None): Message.__init__(self, plain_bits, pause, message_type, decoder=decoder, participant=source) SimulatorItem.__init__(self) if timestamp is not None: self.timestamp = timestamp self.destination = destination self.send_recv_messages = [] self.repeat = 1
def get_protocol_from_string(message_strings: list, is_hex=None, default_pause=0, sample_rate=1e6): """ :param message_strings: :param is_hex: None means auto detects :return: """ protocol = ProtocolAnalyzer(None) def parse_line(line: str): # support transcript files e.g 1 (A->B): 10101111 index = line.rfind(" ") line = line[index + 1:] # support pauses given like 100101/10s try: data, pause = line.split(constants.PAUSE_SEP) except ValueError: data, pause = line, str(default_pause) if pause.endswith("ms"): pause = float(pause[:-2]) * float(sample_rate) / 1e3 elif pause.endswith("µs"): pause = float(pause[:-2]) * float(sample_rate) / 1e6 elif pause.endswith("ns"): pause = float(pause[:-2]) * float(sample_rate) / 1e9 elif pause.endswith("s"): pause = float(pause[:-1]) * float(sample_rate) else: pause = float(pause) return data, int(pause) if not is_hex: for line in filter(None, map(str.strip, message_strings)): bits, pause = parse_line(line) try: protocol.messages.append(Message.from_plain_bits_str(bits, pause=pause)) except ValueError: is_hex = True if is_hex is None else is_hex break if is_hex: protocol.messages.clear() lookup = {"{0:0x}".format(i): "{0:04b}".format(i) for i in range(16)} for line in filter(None, map(str.strip, message_strings)): bits, pause = parse_line(line) bit_str = [lookup[bits[i].lower()] for i in range(0, len(bits))] protocol.messages.append(Message.from_plain_bits_str("".join(bit_str), pause=pause)) return protocol
def __demodulate_data(self, data): """ Demodulates received IQ data and adds demodulated bits to messages :param data: :return: """ if self.__are_bits_in_data(data): self.reading_data = True elif self.conseq_non_data == 5: self.reading_data = False self.conseq_non_data = 0 else: self.conseq_non_data += 1 if self.reading_data: self.data_cache.append(data) return elif len(self.data_cache) == 0: return self.signal._fulldata = np.concatenate(self.data_cache) self.data_cache.clear() self.signal._qad = None bit_len = self.signal.bit_len ppseq = grab_pulse_lens(self.signal.qad, self.signal.qad_center, self.signal.tolerance, self.signal.modulation_type) bit_data, pauses, bit_sample_pos = self._ppseq_to_bits(ppseq, bit_len) i = 0 first_msg = True for bits, pause in zip(bit_data, pauses): if first_msg or self.messages[-1].pause > 8 * bit_len: # Create new Message middle_bit_pos = bit_sample_pos[i][int(len(bits) / 2)] start, end = middle_bit_pos, middle_bit_pos + bit_len rssi = np.mean(np.abs(self.signal._fulldata[start:end])) message = Message(bits, pause, bit_len=bit_len, rssi=rssi, message_type=self.default_message_type, decoder=self.decoder) self.messages.append(message) first_msg = False else: # Append to last message message = self.messages[-1] nzeros = int(np.round(message.pause / bit_len)) message.plain_bits.extend([False] * nzeros) message.plain_bits.extend(bits) message.pause = pause i += 1
def message_to_string(self, message: Message, view: int, include_timestamps=True): msg_str_data = [] if include_timestamps: msg_date = datetime.fromtimestamp(message.timestamp) msg_str_data.append(msg_date.strftime("[%Y-%m-%d %H:%M:%S.%f]")) msg_str_data.append(message.view_to_string(view, decoded=True, show_pauses=False)) return " ".join(msg_str_data)
def check_for_data(self): old_index = 0 while self.is_running: time.sleep(0.01) if self.rcv_device.is_raw_mode: if old_index <= self.rcv_device.current_index: data = self.rcv_device.data[old_index:self.rcv_device.current_index] else: data = np.concatenate((self.rcv_device.data[old_index:], self.rcv_device.data[:self.rcv_device.current_index])) old_index = self.rcv_device.current_index self.__demodulate_data(data) elif self.rcv_device.backend == Backends.network: # We receive the bits here for bit_str in self.rcv_device.data: msg = Message.from_plain_bits_str(bit_str) msg.decoder = self.decoder self.messages.append(msg) self.message_sniffed.emit(len(self.messages) - 1) self.rcv_device.free_data() # do not store received bits twice if self.sniff_file and not os.path.isdir(self.sniff_file): plain_bits_str = self.plain_bits_str if plain_bits_str: with open(self.sniff_file, "a") as f: f.write("\n".join(plain_bits_str) + "\n") if not self.__store_data: self.messages.clear()
def test_cli_modulate_messages(self): modulator = Modulator("test") modulator.sample_rate = 2e3 modulator.samples_per_bit = 100 modulator.modulation_type_str = "ASK" modulator.param_for_zero = 0 modulator.param_for_one = 100 bits = "1010111100001" self.assertIsNone(urh_cli.modulate_messages([], modulator)) message = Message.from_plain_bits_str(bits, pause=1000) modulated = urh_cli.modulate_messages([message], modulator) # Demodulate for testing s = Signal("", "", modulation="ASK", sample_rate=2e6) s.bit_len = 100 s.noise_threshold = 0 s._fulldata = modulated pa = ProtocolAnalyzer(s) pa.get_protocol_from_signal() self.assertEqual(len(pa.messages), 1) self.assertEqual(pa.messages[0].plain_bits_str, bits)
def setUp(self): self.protocol = ProtocolAnalyzer(None) with open(get_path_for_data_file("decoded_bits.txt")) as f: for line in f: self.protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", ""))) self.protocol.messages[-1].message_type = self.protocol.default_message_type # Assign participants alice = Participant("Alice", "A") bob = Participant("Bob", "B") alice_indices = {1,2,5,6,9,10,13,14,17,18,20,22,23,26,27,30,31,34,35,38,39,41} for i, message in enumerate(self.protocol.messages): if i in alice_indices: message.participant = alice else: message.participant = bob self.assertEqual(self.protocol.num_messages, 42) self.assertEqual(self.protocol.plain_hex_str[0][16:18], "2d") self.decodings = [] self.decodings.append(Encoding(['Non Return To Zero (NRZ)'])) self.decodings.append(Encoding(['Non Return To Zero Inverted (NRZ-I)', 'Invert'])) self.decodings.append(Encoding(['Manchester I', 'Edge Trigger'])) self.decodings.append(Encoding(['Manchester II', 'Edge Trigger', 'Invert'])) self.decodings.append(Encoding(['Differential Manchester', 'Edge Trigger', 'Differential Encoding', ])) self.decodings.append(Encoding(['DeWhitening Special', constants.DECODING_DATAWHITENING, '0x9a7d9a7d;0x21'])) self.decodings.append(Encoding(['DeWhitening', constants.DECODING_DATAWHITENING, '0x67686768;0x21']))
def test_format_finding_enocean(self): enocean_protocol = ProtocolAnalyzer(None) with open(get_path_for_data_file("enocean_bits.txt")) as f: for line in f: enocean_protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", ""))) enocean_protocol.messages[-1].message_type = enocean_protocol.default_message_type preamble_start = 3 preamble_end = 10 sof_start = 11 sof_end = 14 preamble_label = ProtocolLabel(name=self.preamble_field_type.caption, field_type=self.preamble_field_type, start=preamble_start, end=preamble_end, color_index=0) sync_label = ProtocolLabel(name=self.sync_field_type.caption, field_type=self.sync_field_type, start=sof_start, end=sof_end, color_index=1) ff = FormatFinder(enocean_protocol, self.participants, field_types=self.field_types) ff.perform_iteration() self.assertEqual(len(enocean_protocol.message_types), 1) self.assertIn(preamble_label, enocean_protocol.default_message_type) self.assertIn(sync_label, enocean_protocol.default_message_type) self.assertTrue( not any(lbl.name == self.length_field_type.caption for lbl in enocean_protocol.default_message_type)) self.assertTrue(not any("address" in lbl.name.lower() for lbl in enocean_protocol.default_message_type))
def generate_random_messages(num_messages: int, num_bits: int, preamble: str, sync: str, eof: str, message_pause: int): return [ Message.from_plain_bits_str( generate_message_bits(num_bits, preamble, sync, eof), pause=message_pause ) for _ in range(num_messages) ]
def new_from_xml(cls, tag: ET.Element, participants, decoders=None, message_types=None): msg = Message.new_from_xml(tag.find("message"), participants=participants, decoders=decoders, message_types=message_types) destination = Participant.find_matching(tag.get("destination_id", ""), participants) return SimulatorMessage(destination, msg.plain_bits, msg.pause, msg.message_type, msg.decoder, msg.participant, timestamp=msg.timestamp)
def add_plain_bits_from_txt(self, filename: str): protocol = ProtocolAnalyzer(None) protocol.filename = filename with open(filename) as f: for line in f: protocol.messages.append(Message.from_plain_bits_str(line.strip())) self.compare_frame_controller.add_protocol(protocol) self.compare_frame_controller.refresh() self.__add_empty_frame_for_filename(protocol, filename)
def log_message_labels(self, message: Message): message.split(decode=False) for lbl in message.message_type: if not lbl.logging_active: continue try: data = message.plain_bits[lbl.start:lbl.end] except IndexError: return None lsb = lbl.display_bit_order_index == 1 lsd = lbl.display_bit_order_index == 2 data = util.convert_bits_to_string(data, lbl.display_format_index, pad_zeros=True, lsb=lsb, lsd=lsd) if data is None: continue log_msg = lbl.name + ": " + HTMLFormatter.monospace(data) self.log_messages.append(HTMLFormatter.indent_string(log_msg))
def get_protocol_from_string(message_strings: list): protocol = ProtocolAnalyzer(None) is_hex = False for line in filter(None, map(str.strip, message_strings)): # support transcript files e.g 1 (A->B): 10101111 index = line.rfind(" ") try: protocol.messages.append(Message.from_plain_bits_str(line[index + 1:])) except ValueError: is_hex = True break if is_hex: protocol.messages.clear() lookup = {"{0:0x}".format(i): "{0:04b}".format(i) for i in range(16)} for line in filter(None, map(str.strip, message_strings)): # support transcript files e.g 1 (A->B): 10101111 index = line.rfind(" ") bit_str = [lookup[line[i].lower()] for i in range(index+1, len(line))] protocol.messages.append(Message.from_plain_bits_str("".join(bit_str))) return protocol
def test_assign_decodings(self): self.undecoded_protocol = ProtocolAnalyzer(None) with open(get_path_for_data_file("undecoded.txt")) as f: for line in f: self.undecoded_protocol.messages.append(Message.from_plain_bits_str(line.replace("\n", ""))) self.undecoded_protocol.auto_assign_decodings(self.decodings) for i, message in enumerate(self.undecoded_protocol.messages): if message.plain_hex_str[8:16] == "9a7d9a7d": self.assertEqual(message.decoder.name, "DeWhitening Special", msg=str(i)) elif message.plain_hex_str[8:16] == "67686768": self.assertEqual(message.decoder.name, "DeWhitening", msg=str(i))
def from_xml_tag(self, root: ET.Element, read_bits=False, participants=None, decodings=None): if not root: return None if root.find("modulators") and hasattr(self, "modulators"): self.modulators[:] = [] for mod_tag in root.find("modulators").findall("modulator"): self.modulators.append(Modulator.from_xml(mod_tag)) decoders = self.read_decoders_from_xml_tag(root) if decodings is None else decodings if participants is None: participants = self.read_participants_from_xml_tag(root) if read_bits: self.messages[:] = [] try: message_types = [] for message_type_tag in root.find("message_types").findall("message_type"): message_types.append(MessageType.from_xml(message_type_tag)) except AttributeError: message_types = [] for message_type in message_types: if message_type not in self.message_types: self.message_types.append(message_type) try: message_tags = root.find("messages").findall("message") for i, message_tag in enumerate(message_tags): if read_bits: message = Message.from_plain_bits_str(bits=message_tag.get("bits")) message.from_xml(tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types) self.messages.append(message) else: try: self.messages[i].from_xml(tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types) except IndexError: pass # Part of signal was copied in last session but signal was not saved except AttributeError: pass
def detect_source_destination(self, message: Message): participants = self.simulator_config.participants source = None if len(participants) < 2 else participants[0] destination = self.simulator_config.broadcast_part if message.participant: source = message.participant dst_address_label = next((lbl for lbl in message.message_type if lbl.field_type and lbl.field_type.function == FieldType.Function.DST_ADDRESS), None) if dst_address_label: start, end = message.get_label_range(dst_address_label, view=1, decode=True) dst_address = message.decoded_hex_str[start:end] dst = next((p for p in participants if p.address_hex == dst_address), None) if dst is not None and dst != source: destination = dst return source, destination
def from_xml_tag(self, root: ET.Element, read_bits=False, participants=None, decodings=None): if not root: return None decoders = Encoding.read_decoders_from_xml_tag(root) if decodings is None else decodings if participants is None: participants = Participant.read_participants_from_xml_tag(root) if read_bits: self.messages[:] = [] try: message_types = [] for message_type_tag in root.find("message_types").findall("message_type"): message_types.append(MessageType.from_xml(message_type_tag)) except AttributeError: message_types = [] for message_type in message_types: if message_type not in self.message_types: self.message_types.append(message_type) try: message_tags = root.find("messages").findall("message") for i, message_tag in enumerate(message_tags): if read_bits: self.messages.append(Message.new_from_xml(tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types)) else: try: self.messages[i].from_xml(tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types) except IndexError: pass # Part of signal was copied in last session but signal was not saved except AttributeError: pass
def get_protocol_from_signal(self): signal = self.signal if signal is None: self.messages = None return if self.messages is not None: self.messages[:] = [] else: self.messages = [] bit_len = signal.bit_len rel_symbol_len = self._read_symbol_len() self.used_symbols.clear() ppseq = signalFunctions.grab_pulse_lens(signal.qad, signal.qad_center, signal.tolerance, signal.modulation_type) bit_data, pauses, bit_sample_pos = self._ppseq_to_bits( ppseq, bit_len, rel_symbol_len) i = 0 for bits, pause in zip(bit_data, pauses): middle_bit_pos = bit_sample_pos[i][int(len(bits) / 2)] start, end = middle_bit_pos, middle_bit_pos + bit_len rssi = np.mean(np.abs(signal._fulldata[start:end])) message = Message(bits, pause, message_type=self.default_message_type, bit_len=bit_len, rssi=rssi, decoder=self.decoder, bit_sample_pos=bit_sample_pos[i]) self.messages.append(message) i += 1 self.qt_signals.protocol_updated.emit()
def on_rcv_thread_index_changed(self, old_index, new_index): old_nmsgs = len(self.messages) if self.rcv_device.backend in (Backends.native, Backends.grc): if old_index == new_index: return self.__demodulate_data(self.rcv_device.data[old_index:new_index]) elif self.rcv_device.backend == Backends.network: # We receive the bits here for bit_str in self.rcv_device.data: msg = Message.from_plain_bits_str(bit_str) msg.decoder = self.decoder self.messages.append(msg) self.rcv_device.free_data() # do not store received bits twice self.qt_signals.data_sniffed.emit(old_nmsgs) if self.sniff_file and not os.path.isdir(self.sniff_file): with open(self.sniff_file, "a") as myfile: myfile.write("\n".join(self.plain_bits_str)) if not self.__store_data: self.messages.clear()
def test_configure_crc_ranges(self): checksum_label = ChecksumLabel( "checksum_label", 50, 100, 0, FieldType("crc", FieldType.Function.CHECKSUM)) crc_widget_controller = ChecksumWidgetController( checksum_label, Message([0] * 100, 0, MessageType("test")), 0) model = crc_widget_controller.data_range_table_model self.assertEqual(model.data(model.index(0, 0)), 1) self.assertEqual(model.data(model.index(0, 1)), 50) self.assertEqual(model.rowCount(), 1) crc_widget_controller.ui.btnAddRange.click() self.assertEqual(model.rowCount(), 2) crc_widget_controller.ui.btnAddRange.click() self.assertEqual(model.rowCount(), 3) crc_widget_controller.ui.btnRemoveRange.click() self.assertEqual(model.rowCount(), 2) crc_widget_controller.ui.btnRemoveRange.click() self.assertEqual(model.rowCount(), 1) crc_widget_controller.ui.btnRemoveRange.click() self.assertEqual(model.rowCount(), 1)
def get_protocol_from_signal(self): signal = self.signal if signal is None: self.messages = None return if self.messages is not None: self.messages[:] = [] else: self.messages = [] bit_len = signal.bit_len try: ppseq = signalFunctions.grab_pulse_lens(signal.qad, signal.qad_center, signal.tolerance, signal.modulation_type, signal.bit_len) except TypeError: # Remove this check in version 1.7 print("Extension method has changed! To fix this, first move to URHs base directory " "then recompile the extensions using the following command:") print("python3 src/urh/cythonext/build.py") print("and finally restart the application") sys.exit(1) bit_data, pauses, bit_sample_pos = self._ppseq_to_bits(ppseq, bit_len, pause_threshold=signal.pause_threshold) i = 0 for bits, pause in zip(bit_data, pauses): middle_bit_pos = bit_sample_pos[i][int(len(bits) / 2)] start, end = middle_bit_pos, middle_bit_pos + bit_len rssi = np.mean(np.abs(signal.data[start:end])) message = Message(bits, pause, message_type=self.default_message_type, bit_len=bit_len, rssi=rssi, decoder=self.decoder, bit_sample_pos=bit_sample_pos[i]) self.messages.append(message) i += 1 self.qt_signals.protocol_updated.emit()
def detect_source_destination(self, message: Message): participants = self.simulator_config.participants source = None if len(participants) < 2 else participants[0] destination = self.simulator_config.broadcast_part if message.participant: source = message.participant dst_address_label = next( (lbl for lbl in message.message_type if lbl.field_type and lbl.field_type.function == FieldType.Function.DST_ADDRESS), None) if dst_address_label: start, end = message.get_label_range(dst_address_label, view=1, decode=True) dst_address = message.decoded_hex_str[start:end] dst = next( (p for p in participants if p.address_hex == dst_address), None) if dst is not None and dst != source: destination = dst return source, destination
def __build_protocol(self): result = ProtocolAnalyzer(signal=None) for _ in range(self.NUM_MESSAGES): b = Message([True] * self.BITS_PER_MESSAGE, pause=1000, message_type=result.default_message_type) result.messages.append(b) return result
def __demodulate_data(self, data): """ Demodulates received IQ data and adds demodulated bits to messages :param data: :return: """ if len(data) == 0: return power_spectrum = data.real**2.0 + data.imag**2.0 is_above_noise = np.sqrt( np.mean(power_spectrum)) > self.signal.noise_threshold if self.adaptive_noise and not is_above_noise: self.signal.noise_threshold = 0.9 * self.signal.noise_threshold + 0.1 * np.sqrt( np.max(power_spectrum)) if is_above_noise: self.__add_to_buffer(data) self.pause_length = 0 if not self.__buffer_is_full(): return else: self.pause_length += len(data) if self.pause_length < 10 * self.signal.samples_per_symbol: self.__add_to_buffer(data) if not self.__buffer_is_full(): return if self.__current_buffer_index == 0: return # clear cache and start a new message self.signal.iq_array = IQArray( self.__buffer[0:self.__current_buffer_index]) self.__clear_buffer() self.signal._qad = None samples_per_symbol = self.signal.samples_per_symbol if self.automatic_center: self.signal.center = AutoInterpretation.detect_center( self.signal.qad, max_size=150 * samples_per_symbol) ppseq = grab_pulse_lens(self.signal.qad, self.signal.center, self.signal.tolerance, self.signal.modulation_type, self.signal.samples_per_symbol, self.signal.bits_per_symbol, self.signal.center_spacing) bit_data, pauses, bit_sample_pos = self._ppseq_to_bits( ppseq, samples_per_symbol, self.signal.bits_per_symbol, write_bit_sample_pos=False) for bits, pause in zip(bit_data, pauses): message = Message(bits, pause, samples_per_symbol=samples_per_symbol, message_type=self.default_message_type, decoder=self.decoder) self.messages.append(message) self.message_sniffed.emit(len(self.messages) - 1)
def get_protocol_from_string(message_strings: list, is_hex=None, default_pause=0, sample_rate=1e6): """ :param message_strings: :param is_hex: None means auto detects :return: """ protocol = ProtocolAnalyzer(None) def parse_line(line: str): # support transcript files e.g 1 (A->B): 10101111 index = line.rfind(" ") line = line[index + 1:] # support pauses given like 100101/10s try: data, pause = line.split(constants.PAUSE_SEP) except ValueError: data, pause = line, str(default_pause) if pause.endswith("ms"): pause = float(pause[:-2]) * float(sample_rate) / 1e3 elif pause.endswith("µs"): pause = float(pause[:-2]) * float(sample_rate) / 1e6 elif pause.endswith("ns"): pause = float(pause[:-2]) * float(sample_rate) / 1e9 elif pause.endswith("s"): pause = float(pause[:-1]) * float(sample_rate) else: pause = float(pause) return data, int(pause) if not is_hex: for line in filter(None, map(str.strip, message_strings)): bits, pause = parse_line(line) try: protocol.messages.append( Message.from_plain_bits_str(bits, pause=pause)) except ValueError: is_hex = True if is_hex is None else is_hex break if is_hex: protocol.messages.clear() lookup = { "{0:0x}".format(i): "{0:04b}".format(i) for i in range(16) } for line in filter(None, map(str.strip, message_strings)): bits, pause = parse_line(line) bit_str = [ lookup[bits[i].lower()] for i in range(0, len(bits)) ] protocol.messages.append( Message.from_plain_bits_str("".join(bit_str), pause=pause)) return protocol
def from_xml_tag(self, root: ET.Element, read_bits=False, participants=None, decodings=None): if not root: return None if root.find("modulators") and hasattr(self, "modulators"): self.modulators[:] = [] for mod_tag in root.find("modulators").findall("modulator"): self.modulators.append(Modulator.from_xml(mod_tag)) decoders = self.read_decoders_from_xml_tag( root) if decodings is None else decodings self.used_symbols.clear() try: for symbol_tag in root.find("symbols").findall("symbol"): s = Symbol(symbol_tag.get("name"), int(symbol_tag.get("nbits")), int(symbol_tag.get("pulsetype")), int(symbol_tag.get("nsamples"))) self.used_symbols.add(s) except AttributeError: pass if participants is None: participants = self.read_participants_from_xml_tag(root) if read_bits: self.messages[:] = [] try: message_types = [] for message_type_tag in root.find("message_types").findall( "message_type"): message_types.append(MessageType.from_xml(message_type_tag)) except AttributeError: message_types = [] for message_type in message_types: if message_type not in self.message_types: self.message_types.append(message_type) try: message_tags = root.find("messages").findall("message") for i, message_tag in enumerate(message_tags): if read_bits: message = Message.from_plain_bits_str( bits=message_tag.get("bits"), symbols={s.name: s for s in self.used_symbols}) message.from_xml(tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types) self.messages.append(message) else: try: self.messages[i].from_xml( tag=message_tag, participants=participants, decoders=decoders, message_types=self.message_types) except IndexError: pass # Part of signal was copied in last session but signal was not saved except AttributeError: pass
def process_message(self): assert isinstance(self.current_item, SimulatorMessage) msg = self.current_item if msg.source is None: return new_message = self.generate_message_from_template(msg) if msg.source.simulate: # we have to send a message sender = self.sender if sender is None: self.log_message("Fatal: No sender configured") return for lbl in new_message.message_type: if isinstance(lbl.label, ChecksumLabel): checksum = lbl.label.calculate_checksum_for_message(new_message, use_decoded_bits=False) label_range = new_message.get_label_range(lbl=lbl.label, view=0, decode=False) start, end = label_range[0], label_range[1] new_message.plain_bits[start:end] = checksum + array.array("B", [0] * ( (end - start) - len(checksum))) self.transcript.append(msg.source, msg.destination, new_message, msg.index()) self.send_message(new_message, msg.repeat, sender, msg.modulator_index) self.log_message("Sending message " + msg.index()) self.log_message_labels(new_message) msg.send_recv_messages.append(new_message) self.last_sent_message = msg else: # we have to receive a message self.log_message("<i>Waiting for message {}</i>".format(msg.index())) sniffer = self.sniffer if sniffer is None: self.log_message("Fatal: No sniffer configured") return retry = 0 max_retries = self.project_manager.simulator_retries while self.is_simulating and not self.simulation_is_finished() and retry < max_retries: received_msg = self.receive_message(sniffer) if not self.is_simulating: return if received_msg is None: if self.project_manager.simulator_error_handling_index == 0: self.resend_last_message() retry += 1 continue elif self.project_manager.simulator_error_handling_index == 1: self.stop() return elif self.project_manager.simulator_error_handling_index == 2: self.do_restart = True return received_msg.decoder = new_message.decoder received_msg.message_type = new_message.message_type check_result, error_msg = self.check_message(received_msg, new_message, retry=retry, msg_index=msg.index()) if check_result: decoded_msg = Message(received_msg.decoded_bits, 0, received_msg.message_type, decoder=received_msg.decoder) msg.send_recv_messages.append(decoded_msg) self.transcript.append(msg.source, msg.destination, decoded_msg, msg.index()) self.log_message("Received message " + msg.index() + ": ") self.log_message_labels(decoded_msg) return elif self.verbose: self.log_message(error_msg) retry += 1 if retry == self.project_manager.simulator_retries: self.log_message("Message " + msg.index() + " not received") self.stop()
def __get_modulator_of_message(self, message: Message) -> Modulator: if message.modulator_index > len(self.modulators) - 1: message.modulator_index = 0 return self.modulators[message.modulator_index]
def from_binary(self, filename: str): aggregated = np.fromfile(filename, dtype=np.uint8) unaggregated = [int(b) for n in aggregated for b in "{0:08b}".format(n)] self.messages.append(Message(unaggregated, 0, self.default_message_type))
def __create_messages(self): mt = MessageType("test") return [ Message([True] * self.BITS_PER_MESSAGE, 1000, mt) for _ in range(self.NUM_MESSAGES) ]
def generate_message(self, message_type=None, data="0x00", source: Participant = None, destination: Participant = None): for participant in (source, destination): if isinstance( participant, Participant) and participant not in self.participants: self.participants.append(participant) if isinstance(message_type, MessageType): message_type_index = self.protocol.message_types.index( message_type) elif isinstance(message_type, int): message_type_index = message_type else: message_type_index = 0 data = self.to_bits(data) mt = self.protocol.message_types[ message_type_index] # type: MessageType mt.sort() bits = [] start = 0 data_label_present = mt.get_first_label_with_type( FieldType.Function.DATA) is not None if data_label_present: message_length = mt[-1].end - 1 else: message_length = mt[-1].end - 1 + len(data) checksum_labels = [] for lbl in mt: # type: ProtocolLabel bits.append("0" * (lbl.start - start)) len_field = lbl.end - lbl.start # in bits if isinstance(lbl, ChecksumLabel): checksum_labels.append(lbl) continue # processed last if lbl.field_type.function == FieldType.Function.PREAMBLE: preamble = self.preambles_by_message_type[mt] assert len(preamble) == len_field bits.append(preamble) message_length -= len(preamble) elif lbl.field_type.function == FieldType.Function.SYNC: sync = self.syncs_by_message_type[mt] assert len(sync) == len_field bits.append(sync) message_length -= len(sync) elif lbl.field_type.function == FieldType.Function.LENGTH: value = int(math.ceil(message_length / 8)) if not self.length_in_bytes: value *= 8 bits.append(self.decimal_to_bits(value, len_field)) elif lbl.field_type.function == FieldType.Function.TYPE: bits.append( self.decimal_to_bits( self.message_type_codes[mt] % (2**len_field), len_field)) elif lbl.field_type.function == FieldType.Function.SEQUENCE_NUMBER: bits.append( self.decimal_to_bits( self.sequence_numbers[mt] % (2**len_field), len_field)) elif lbl.field_type.function == FieldType.Function.DST_ADDRESS: dst_bits = self.__get_address_for_participant(destination) if len(dst_bits) != len_field: raise ValueError( "Length of dst ({0} bits) != length dst field ({1} bits)" .format(len(dst_bits), len_field)) bits.append(dst_bits) elif lbl.field_type.function == FieldType.Function.SRC_ADDRESS: src_bits = self.__get_address_for_participant(source) if len(src_bits) != len_field: raise ValueError( "Length of src ({0} bits) != length src field ({1} bits)" .format(len(src_bits), len_field)) bits.append(src_bits) elif lbl.field_type.function == FieldType.Function.DATA: if len(data) != len_field: raise ValueError( "Length of data ({} bits) != length data field ({} bits)" .format(len(data), len_field)) bits.append(data) start = lbl.end if not data_label_present: bits.append(data) msg = Message.from_plain_bits_str("".join(bits)) msg.message_type = mt msg.participant = source self.sequence_numbers[mt] += self.sequence_number_increment for checksum_label in checksum_labels: msg[checksum_label.start:checksum_label. end] = checksum_label.calculate_checksum_for_message( msg, False) self.protocol.messages.append(msg)
def push_data(self, data: np.ndarray): self.ringbuffer.push(data) if __name__ == '__main__': from urh.dev.BackendHandler import BackendHandler from urh.signalprocessing.Message import Message from urh.signalprocessing.MessageType import MessageType from urh.signalprocessing.Modulator import Modulator from urh.util.Logger import logger import time endless_sender = EndlessSender(BackendHandler(), "HackRF") msg = Message([1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4, 0, MessageType("empty_message_type")) modulator = Modulator("test_modulator") modulator.samples_per_bit = 1000 modulator.carrier_freq_hz = 55e3 logger.debug("Starting endless sender") endless_sender.start() time.sleep(1) logger.debug("Pushing data") endless_sender.push_data(modulator.modulate(msg.encoded_bits)) logger.debug("Pushed data") time.sleep(5) logger.debug("Stopping endless sender") endless_sender.stop() time.sleep(1)