class ThroughtPutTest: def __init__(self): self.argparser = argparse.ArgumentParser( fromfile_prefix_chars="@", description="Test throughput over 2 serial D7 modems") self.argparser.add_argument("-n", "--msg-count", help="number of messages to transmit", type=int, default=10) self.argparser.add_argument( "-p", "--payload-size", help="number of bytes of (appl level) payload to transmit", type=int, default=50) self.argparser.add_argument( "-sw", "--serial-transmitter", help="serial device /dev file transmitter node", default=None) self.argparser.add_argument( "-sr", "--serial-receiver", help="serial device /dev file receiver node", default=None) self.argparser.add_argument("-r", "--rate", help="baudrate for serial device", type=int, default=115200) self.argparser.add_argument( "-uid", "--unicast-uid", help="UID to use for unicast transmission, " "when not using receiver " "(in hexstring, for example 0xb57000009151d)", default=None) self.argparser.add_argument( "-to", "--receiver-timeout", help="timeout for the receiver (in seconds)", type=int, default=10) self.argparser.add_argument("-v", "--verbose", help="verbose", default=False, action="store_true") self.config = self.argparser.parse_args() if self.config.serial_transmitter == None and self.config.serial_receiver == None: self.argparser.error( "At least a transmitter or receiver is required.") if self.config.serial_receiver == None and self.config.unicast_uid == None: self.argparser.error( "When running without receiver a --unicast-uid parameter is required." ) if self.config.serial_transmitter == None: self.transmitter_modem = None print("Running without transmitter") else: self.transmitter_modem = Modem(self.config.serial_transmitter, self.config.rate, None, show_logging=self.config.verbose) access_profile = AccessProfile( channel_header=ChannelHeader( channel_band=ChannelBand.BAND_868, channel_coding=ChannelCoding.PN9, channel_class=ChannelClass.NORMAL_RATE), sub_profiles=[ SubProfile(subband_bitmap=0x01, scan_automation_period=CT(exp=0, mant=0)), SubProfile(), SubProfile(), SubProfile() ], sub_bands=[ SubBand( channel_index_start=0, channel_index_end=0, eirp=10, cca=86 # TODO ) ]) print("Write Access Profile") write_ap_cmd = Command.create_with_write_file_action_system_file( file=AccessProfileFile(access_profile=access_profile, access_specifier=0)) self.transmitter_modem.send_command(write_ap_cmd) if self.config.serial_receiver == None: self.receiver_modem = None print("Running without receiver") else: self.receiver_modem = Modem(self.config.serial_receiver, self.config.rate, self.receiver_cmd_callback, show_logging=self.config.verbose) self.receiver_modem.send_command( Command.create_with_write_file_action_system_file( DllConfigFile(active_access_class=0x01))) print("Receiver scanning on Access Class = 0x01") def start(self): self.received_commands = defaultdict(list) payload = range(self.config.payload_size) if self.receiver_modem != None: addressee_id = int(self.receiver_modem.uid, 16) else: addressee_id = int(self.config.unicast_uid, 16) if self.transmitter_modem != None: print( "\n==> broadcast, with QoS, transmitter active access class = 0x01 ====" ) self.transmitter_modem.send_command( Command.create_with_write_file_action_system_file( DllConfigFile(active_access_class=0x01))) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ANY), addressee=Addressee( access_class=0x01, id_type=IdType.NBID, id=CT(exp=0, mant=1) # we expect one responder )) self.start_transmitting( interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print( "\n==> broadcast, no QoS, transmitter active access class = 0x01 ====" ) self.transmitter_modem.send_command( Command.create_with_write_file_action_system_file( DllConfigFile(active_access_class=0x01))) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_NO), addressee=Addressee(access_class=0x01, id_type=IdType.NOID)) self.start_transmitting( interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print( "\n==> unicast, with QoS, transmitter active access class = 0x01" ) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ANY), addressee=Addressee(access_class=0x01, id_type=IdType.UID, id=addressee_id)) self.start_transmitting( interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print( "\n==> unicast, no QoS, transmitter active access class = 0x01" ) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_NO), addressee=Addressee(access_class=0x01, id_type=IdType.UID, id=addressee_id)) self.start_transmitting( interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) else: # receive only self.receiver_modem.start_reading() self.wait_for_receiver(payload) def start_transmitting(self, interface_configuration, payload): print( "Running throughput test with payload size {} and interface_configuration {}\n\nrunning ...\n" .format(len(payload), interface_configuration)) if self.receiver_modem != None: self.received_commands = defaultdict(list) self.receiver_modem.start_reading() command = Command.create_with_return_file_data_action( file_id=0x40, data=payload, interface_type=InterfaceType.D7ASP, interface_configuration=interface_configuration) start = time.time() for i in range(self.config.msg_count): sys.stdout.write("{}/{}\r".format(i + 1, self.config.msg_count)) sys.stdout.flush() self.transmitter_modem.d7asp_fifo_flush(command) end = time.time() print("transmitter: sending {} messages completed in: {} s".format( self.config.msg_count, end - start)) print( "transmitter: throughput = {} bps with a payload size of {} bytes". format((self.config.msg_count * self.config.payload_size * 8) / (end - start), self.config.payload_size)) def wait_for_receiver(self, payload): if self.receiver_modem == None: print( "Running without receiver so we are not waiting for messages to be received ..." ) else: start = time.time() total_recv = 0 while total_recv < self.config.msg_count and time.time( ) - start < self.config.receiver_timeout: total_recv = sum( len(v) for v in self.received_commands.values()) time.sleep(2) print( "waiting for receiver to finish ... (current nr of recv msgs: {})" .format(total_recv)) print("finished receiving or timeout") self.receiver_modem.cancel_read() payload_has_errors = False for sender_cmd in self.received_commands.values(): for cmd in sender_cmd: if type(cmd.actions[0].op ) != ReturnFileData and cmd.actions[ 0].operand.data != payload: payload_has_errors = True print( "receiver: received unexpected command: {}".format( cmd)) if payload_has_errors == False and total_recv == self.config.msg_count: print( "receiver: OK: received {} messages with correct payload:". format(total_recv)) for sender, cmds in self.received_commands.items(): print("\t{}: {}".format(sender, len(cmds))) else: print( "receiver: NOK: received messages {}:".format(total_recv)) for sender, cmds in self.received_commands.items(): print("\t{}: {}".format(sender, len(cmds))) def receiver_cmd_callback(self, cmd): print("recv cmd: ".format(cmd)) if cmd.interface_status != None: uid = cmd.interface_status.operand.interface_status.addressee.id self.received_commands[uid].append(cmd) else: print("Unexpected cmd received, reboot?\n\t{}".format(cmd))
class ChatClient(object): def __init__(self): self.logs = [] self.command = "" self.counter = 0 argparser = argparse.ArgumentParser() argparser.add_argument("-s", "--serial", help="serial device /dev file", default="/dev/tty.usbserial-FTGCT0HY") argparser.add_argument("-b", "--baudrate", help="baudrate for serial device", type=int, default=115200) config = argparser.parse_args() self.modem = Modem(config.serial, config.baudrate, show_logging=False) self.setup_screen() def setup_screen(self): self.screen = curses.initscr() curses.noecho() # no echo, we will render it curses.cbreak() # curses.curs_set(0) # hide cursor, we will fake it with inverted space curses.halfdelay(1) # wait for 1/10 second when waiting for input self.screen.keypad(1) self.setup() def setup(self): (self.height, self.width) = self.screen.getmaxyx() self.setup_viewer_window() self.setup_prompt() self.refresh_logger_window() self.refresh_prompt() def setup_viewer_window(self): # create a pad, taking up the entire window, but the last two lines self.logger = curses.newpad(self.height - 1, self.width) def setup_prompt(self): # create a window, taking up the entire window, but the last two lines self.prompt = curses.newpad(2, self.width) name = "ChatClient" self.prompt.addstr(0, 0, name + " " * (self.width - len(name)), curses.A_REVERSE) self.prompt.addstr(1, 0, "> ") self.update_command() def update_command(self): w = len(self.command) self.prompt.addstr(1, 2, self.command) self.prompt.addstr(1, 2 + w, " ", curses.A_REVERSE) # cursor self.prompt.addstr(1, 3 + w, " " * (self.width - 4 - w)) self.refresh_prompt() def clean_up(self, msg=""): self.clean_up_screen() def clean_up_screen(self): curses.nocbreak() self.screen.keypad(0) curses.echo() curses.endwin() def add(self, text, style=curses.A_NORMAL): text = text.replace('\0', '') self.logs.append({"text": text, "style": style}) self.refresh_logger_window() def log(self, *msg): string = " ".join(map(str, msg)) for line in string.splitlines(): self.add(line) def refresh_logger_window(self): (height, width) = self.screen.getmaxyx() self.logger.erase() for y, line in enumerate(self.logs[-height + 2:]): self.logger.addstr(y, 0, line["text"], line["style"]) self.logger.refresh(0, 0, 0, 0, height - 3, width) def refresh_prompt(self): (height, width) = self.screen.getmaxyx() self.prompt.refresh(0, 0, height - 2, 0, height, width) def process(self): while True: # handle input from user self.handle_input() # Read from D7 modem and decode packets/commands (cmds, info) = self.modem.read() if len(info["errors"]) < 1: if len(cmds) > 0: origin = cmds[ 0].interface_status.operation.operand.interface_status.addressee.id data = cmds[0].actions[0].operation.operand.data self.add(str(origin) + ": " + ''.join(map(str, data))) def handle_input(self): c = self.prompt.getch() if c == curses.ERR: return elif c == curses.KEY_RESIZE: self.setup() elif c == curses.ascii.DEL or c == curses.ascii.BS: self.command = self.command[:-1] elif c == ord('\n'): self.send() self.command = "" else: self.command += chr(c) self.update_command() def send(self): cmd = Command.create_with_return_file_data_action( file_id=0x40, data=map(ord, list(self.command)), interface_type=InterfaceType.D7ASP, interface_configuration=Configuration( qos=QoS(resp_mod=QoS.RESP_MODE_NO), addressee=Addressee(access_class=0, id_type=IdType.BCAST))) self.modem.d7asp_fifo_flush(alp_command=cmd) self.add("me: " + self.command, curses.A_REVERSE)
def received_command_callback(cmd): print cmd argparser = argparse.ArgumentParser() argparser.add_argument("-d", "--device", help="serial device /dev file modem", default="/dev/ttyUSB0") argparser.add_argument("-r", "--rate", help="baudrate for serial device", type=int, default=115200) argparser.add_argument("-v", "--verbose", help="verbose", default=False, action="store_true") config = argparser.parse_args() modem = Modem(config.device, config.rate, receive_callback=received_command_callback, show_logging=config.verbose) modem.d7asp_fifo_flush( alp_command=Command.create_with_read_file_action_system_file( file=UidFile(), interface_type=InterfaceType.D7ASP, interface_configuration=Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ALL), addressee=Addressee( access_class=0, id_type=IdType.NOID ) ) ) ) modem.start_reading() while True: pass
access_class=0, id_type=IdType.BCAST))) last_message = 0 sent = 0 received = 0 def stats(): print "sent", sent, "received", received while True: # Read from D7 modem and decode packets/commands (cmds, info) = modem.read() if len(info["errors"]) < 1: if len(cmds) > 0: received += 1 stats() else: pprint(info) # every second, at random, send a message now = round(time.time()) if last_message < now: last_message = now if random.random() > 0.50: modem.d7asp_fifo_flush(alp_command=cmd) sent += 1 stats()
help="serial device /dev file modem", default="/dev/ttyACM1") argparser.add_argument("-r", "--rate", help="baudrate for serial device", type=int, default=115200) argparser.add_argument("-v", "--verbose", help="verbose", default=False, action="store_true") config = argparser.parse_args() modem = Modem(config.device, config.rate, receive_callback=received_command_callback, show_logging=config.verbose) modem.d7asp_fifo_flush( alp_command=Command.create_with_read_file_action_system_file( file=UidFile(), interface_type=InterfaceType.D7ASP, interface_configuration=Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ALL), addressee=Addressee(access_class=0x01, id_type=IdType.NOID)))) modem.start_reading() while True: pass
class ChatClient(object): def __init__(self): self.logs = [] self.command = "" self.counter = 0 argparser = argparse.ArgumentParser() argparser.add_argument("-s", "--serial", help="serial device /dev file", default="/dev/tty.usbserial-FTGCT0HY") argparser.add_argument("-b", "--baudrate", help="baudrate for serial device", type=int, default=115200) config = argparser.parse_args() self.modem = Modem(config.serial, config.baudrate, show_logging=False) self.setup_screen() def setup_screen(self): self.screen = curses.initscr() curses.noecho() # no echo, we will render it curses.cbreak() # curses.curs_set(0) # hide cursor, we will fake it with inverted space curses.halfdelay(1) # wait for 1/10 second when waiting for input self.screen.keypad(1) self.setup() def setup(self): (self.height, self.width) = self.screen.getmaxyx() self.setup_viewer_window() self.setup_prompt() self.refresh_logger_window() self.refresh_prompt() def setup_viewer_window(self): # create a pad, taking up the entire window, but the last two lines self.logger = curses.newpad(self.height-1, self.width) def setup_prompt(self): # create a window, taking up the entire window, but the last two lines self.prompt = curses.newpad(2, self.width) name = "ChatClient" self.prompt.addstr(0, 0, name + " " * (self.width-len(name)), curses.A_REVERSE) self.prompt.addstr(1, 0, "> ") self.update_command() def update_command(self): w = len(self.command) self.prompt.addstr(1, 2, self.command) self.prompt.addstr(1, 2 + w, " ", curses.A_REVERSE) # cursor self.prompt.addstr(1, 3 + w, " " * (self.width - 4 - w)) self.refresh_prompt() def clean_up(self, msg=""): self.clean_up_screen() def clean_up_screen(self): curses.nocbreak(); self.screen.keypad(0); curses.echo() curses.endwin() def add(self, text, style=curses.A_NORMAL): text = text.replace('\0', '') self.logs.append({ "text": text, "style": style}) self.refresh_logger_window() def log(self, *msg): string = " ".join(map(str, msg)) for line in string.splitlines(): self.add(line) def refresh_logger_window(self): (height, width) = self.screen.getmaxyx() self.logger.erase() for y, line in enumerate(self.logs[-height+2:]): self.logger.addstr(y, 0, line["text"], line["style"]) self.logger.refresh(0, 0, 0, 0, height-3, width) def refresh_prompt(self): (height, width) = self.screen.getmaxyx() self.prompt.refresh(0, 0, height-2, 0, height, width) def process(self): while True: # handle input from user self.handle_input() # Read from D7 modem and decode packets/commands (cmds, info) = self.modem.read() if len(info["errors"]) < 1: if len(cmds) > 0: origin = cmds[0].interface_status.operation.operand.interface_status.addressee.id data = cmds[0].actions[0].operation.operand.data self.add(str(origin) + ": " + ''.join(map(str, data))) def handle_input(self): c = self.prompt.getch() if c == curses.ERR: return elif c == curses.KEY_RESIZE: self.setup() elif c == curses.ascii.DEL or c == curses.ascii.BS: self.command = self.command[:-1] elif c == ord('\n'): self.send() self.command = "" else: self.command += chr(c) self.update_command() def send(self): cmd = Command.create_with_return_file_data_action( file_id=0x40, data=map(ord, list(self.command)), interface_type=InterfaceType.D7ASP, interface_configuration=Configuration( qos=QoS(resp_mod=QoS.RESP_MODE_NO), addressee=Addressee( access_class=0, id_type=IdType.BCAST ) ) ) self.modem.d7asp_fifo_flush(alp_command=cmd) self.add("me: " + self.command, curses.A_REVERSE)
class ThroughtPutTest: def __init__(self): self.argparser = argparse.ArgumentParser( fromfile_prefix_chars="@", description="Test throughput over 2 serial D7 modems" ) self.argparser.add_argument("-n", "--msg-count", help="number of messages to transmit", type=int, default=10) self.argparser.add_argument("-p", "--payload-size", help="number of bytes of (appl level) payload to transmit", type=int, default=50) self.argparser.add_argument("-sw", "--serial-transmitter", help="serial device /dev file transmitter node", default=None) self.argparser.add_argument("-sr", "--serial-receiver", help="serial device /dev file receiver node", default=None) self.argparser.add_argument("-r", "--rate", help="baudrate for serial device", type=int, default=115200) self.argparser.add_argument("-uid", "--unicast-uid", help="UID to use for unicast transmission, " "when not using receiver " "(in hexstring, for example 0xb57000009151d)", default=None) self.argparser.add_argument("-to", "--receiver-timeout", help="timeout for the receiver (in seconds)", type=int, default=10) self.argparser.add_argument("-v", "--verbose", help="verbose", default=False, action="store_true") self.config = self.argparser.parse_args() if self.config.serial_transmitter == None and self.config.serial_receiver == None: self.argparser.error("At least a transmitter or receiver is required.") if self.config.serial_receiver == None and self.config.unicast_uid == None: self.argparser.error("When running without receiver a --unicast-uid parameter is required.") if self.config.serial_transmitter == None: self.transmitter_modem = None print("Running without transmitter") else: self.transmitter_modem = Modem(self.config.serial_transmitter, self.config.rate, None, show_logging=self.config.verbose) access_profile = AccessProfile( scan_type_is_foreground=True, csma_ca_mode=CsmaCaMode.UNC, subnet=03, scan_automation_period=CT(0), subbands=[Subband( channel_header=ChannelHeader(channel_band=ChannelBand.BAND_433, channel_coding=ChannelCoding.PN9, channel_class=ChannelClass.NORMAL_RATE), channel_index_start=16, channel_index_end=16, eirp=10, ccao=0 # TODO ) ] ) print("Write Access Profile") write_ap_cmd = Command.create_with_write_file_action_system_file(file=AccessProfileFile(access_profile=access_profile, access_specifier=0)) self.transmitter_modem.send_command(write_ap_cmd) if self.config.serial_receiver == None: self.receiver_modem = None print("Running without receiver") else: self.receiver_modem = Modem(self.config.serial_receiver, self.config.rate, self.receiver_cmd_callback, show_logging=self.config.verbose) self.receiver_modem.send_command(Command.create_with_write_file_action_system_file(DllConfigFile(active_access_class=2))) print("Receiver scanning on Access Class = 2") def start(self): self.received_commands = defaultdict(list) payload = range(self.config.payload_size) if self.receiver_modem != None: addressee_id = self.receiver_modem.uid else: addressee_id = int(self.config.unicast_uid, 16) if self.transmitter_modem != None: print("\n==> broadcast, with QoS, transmitter active access class = 0 ====") self.transmitter_modem.send_command(Command.create_with_write_file_action_system_file(DllConfigFile(active_access_class=0))) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ANY), addressee=Addressee( access_class=2, id_type=IdType.NOID ) ) self.start_transmitting(interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print("\n==> broadcast, no QoS, transmitter active access class = 0 ====") self.transmitter_modem.send_command(Command.create_with_write_file_action_system_file(DllConfigFile(active_access_class=0))) interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_NO), addressee=Addressee( access_class=2, id_type=IdType.NOID ) ) self.start_transmitting(interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print("\n==> unicast, with QoS, transmitter active access class = 0") interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_ANY), addressee=Addressee( access_class=2, id_type=IdType.UID, id=addressee_id ) ) self.start_transmitting(interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) print("\n==> unicast, no QoS, transmitter active access class = 0") interface_configuration = Configuration( qos=QoS(resp_mod=ResponseMode.RESP_MODE_NO), addressee=Addressee( access_class=2, id_type=IdType.UID, id=addressee_id ) ) self.start_transmitting(interface_configuration=interface_configuration, payload=payload) self.wait_for_receiver(payload) else: # receive only self.receiver_modem.start_reading() self.wait_for_receiver(payload) def start_transmitting(self, interface_configuration, payload): print("Running throughput test with payload size {} and interface_configuration {}\n\nrunning ...\n".format(len(payload), interface_configuration)) if self.receiver_modem != None: self.received_commands = defaultdict(list) self.receiver_modem.start_reading() command = Command.create_with_return_file_data_action( file_id=0x40, data=payload, interface_type=InterfaceType.D7ASP, interface_configuration=interface_configuration ) start = time.time() for i in range(self.config.msg_count): sys.stdout.write("{}/{}\r".format(i + 1, self.config.msg_count)) sys.stdout.flush() self.transmitter_modem.d7asp_fifo_flush(command) end = time.time() print("transmitter: sending {} messages completed in: {} s".format(self.config.msg_count, end - start)) print("transmitter: throughput = {} bps with a payload size of {} bytes".format( (self.config.msg_count * self.config.payload_size * 8) / (end - start), self.config.payload_size) ) def wait_for_receiver(self, payload): if self.receiver_modem == None: print("Running without receiver so we are not waiting for messages to be received ...") else: start = time.time() total_recv = 0 while total_recv < self.config.msg_count and time.time() - start < self.config.receiver_timeout: total_recv = sum(len(v) for v in self.received_commands.values()) time.sleep(2) print("waiting for receiver to finish ... (current nr of recv msgs: {})".format(total_recv)) print("finished receiving or timeout") self.receiver_modem.cancel_read() payload_has_errors = False for sender_cmd in self.received_commands.values(): for cmd in sender_cmd: if type(cmd.actions[0].op) != ReturnFileData and cmd.actions[0].operand.data != payload: payload_has_errors = True print ("receiver: received unexpected command: {}".format(cmd)) if payload_has_errors == False and total_recv == self.config.msg_count: print("receiver: OK: received {} messages with correct payload:".format(total_recv)) for sender, cmds in self.received_commands.items(): print("\t{}: {}".format(sender, len(cmds))) else: print("receiver: NOK: received messages {}:".format(total_recv)) for sender, cmds in self.received_commands.items(): print("\t{}: {}".format(sender, len(cmds))) def receiver_cmd_callback(self, cmd): if cmd.interface_status != None: uid = cmd.interface_status.operand.interface_status.addressee.id self.received_commands[uid].append(cmd) else: print("Unexpected cmd received, reboot?\n\t{}".format(cmd))
id_type=IdType.BCAST ) ) ) last_message = 0 sent = 0 received = 0 def stats(): print "sent", sent, "received", received while True: # Read from D7 modem and decode packets/commands (cmds, info) = modem.read() if len(info["errors"]) < 1: if len(cmds) > 0: received += 1 stats() else: pprint(info) # every second, at random, send a message now = round(time.time()) if last_message < now: last_message = now if random.random() > 0.50: modem.d7asp_fifo_flush(alp_command=cmd) sent += 1 stats()