Exemple #1
0
    def __init__(self,
                 device,
                 baudrate,
                 unsolicited_response_received_callback=None,
                 skip_alp_parsing=False):
        self.log = logging.getLogger(__name__)
        self.parser = Parser(skip_alp_parsing)
        self.config = {"device": device, "baudrate": baudrate}

        self.uid = None
        self.firmware_version = None
        self.skip_alp_parsing = skip_alp_parsing
        self._sync_execution_response_cmds = []
        self._sync_execution_tag_id = None
        self._sync_execution_completed = False
        self._unsolicited_responses_received = []
        self._read_async_active = False
        self.unsolicited_response_received_callback = unsolicited_response_received_callback
        self.connected = False
        self.dev = serial.Serial(
            port=self.config["device"],
            baudrate=self.config["baudrate"],
            timeout=None,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS,
            xonxoff=False,
            rtscts=False,
            dsrdtr=False,
            exclusive=True,
        )

        self.dev.flush()  # ignore possible buffered data

        self.start_reading()
Exemple #2
0
    def __init__(self, device, baudrate,
                 unsolicited_response_received_callback):
        self.log = logging.getLogger(__name__)
        self.parser = Parser()
        self.config = {"device": device, "baudrate": baudrate}

        self.uid = None
        self.firmware_version = None
        self._sync_execution_response_cmds = []
        self._sync_execution_tag_id = None
        self._sync_execution_completed = False
        self._unsolicited_responses_received = []
        self._read_async_active = False
        self.unsolicited_response_received_callback = unsolicited_response_received_callback

        connected = self._connect_serial_modem()
        if connected:
            self.log.info(
                "connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}"
                .format(self.config["device"], self.uid,
                        self.firmware_version.d7ap_version,
                        self.firmware_version.application_name,
                        self.firmware_version.git_sha1))
        else:
            raise ModemConnectionError
Exemple #3
0
 def __init__(self, device, baudrate, show_logging=True):
   self.show_logging = show_logging
   self.parser = Parser()
   self.config = {
     "device"   : device,
     "baudrate" : baudrate
   }
   self.setup_serial_device()
    def __init__(self, device, baudrate, receive_callback, show_logging=True):
        self.show_logging = show_logging
        self.parser = Parser()
        self.config = {"device": device, "baudrate": baudrate}

        self.uid = None
        self.firmware_version = None
        connected = self._connect_serial_modem()
        if connected:
            print(
                "connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}"
                .format(self.config["device"], self.uid,
                        self.firmware_version.d7ap_version,
                        self.firmware_version.application_name,
                        self.firmware_version.git_sha1))
        else:
            raise ModemConnectionError

        self.read_async_active = False
        self.receive_callback = receive_callback
Exemple #5
0
  def __init__(self, device, baudrate, receive_callback, show_logging=True):
    self.show_logging = show_logging
    self.parser = Parser()
    self.config = {
      "device"   : device,
      "baudrate" : baudrate
    }

    self.uid = None
    self.firmware_version = None
    connected = self._connect_serial_modem()
    if connected:
      print("connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}".format(
        self.config["device"], hex(self.uid), self.firmware_version.d7ap_version,
        self.firmware_version.application_name, self.firmware_version.git_sha1)
      )
    else:
      raise ModemConnectionError

    self.read_async_active = False
    self.receive_callback = receive_callback
Exemple #6
0
class Modem:
  def __init__(self, device, baudrate, receive_callback, show_logging=True):
    self.show_logging = show_logging
    self.parser = Parser()
    self.config = {
      "device"   : device,
      "baudrate" : baudrate
    }

    self.uid = None
    self.firmware_version = None
    connected = self._connect_serial_modem()
    if connected:
      print("connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}".format(
        self.config["device"], hex(self.uid), self.firmware_version.d7ap_version,
        self.firmware_version.application_name, self.firmware_version.git_sha1)
      )
    else:
      raise ModemConnectionError

    self.read_async_active = False
    self.receive_callback = receive_callback

  def _connect_serial_modem(self):
    self.dev = serial.Serial(
      port     = self.config["device"],
      baudrate = self.config["baudrate"],
      timeout  = 0.5,
    )

    read_modem_info_action = Command.create_with_read_file_action_system_file(UidFile())
    read_modem_info_action.add_action(
      RegularAction(
        operation=ReadFileData(
          operand=DataRequest(
            offset=Offset(id=FirmwareVersionFile().id, offset=0),  # TODO offset size
            length=FirmwareVersionFile().length
          )
        )
      )
    )

    self.send_command(read_modem_info_action)

    # read thread not yet running here, read sync
    start_time = datetime.now()
    timeout = False
    while not timeout:
      commands, info = self.read()
      for command in commands:
        for action in command.actions:
          if type(action) is RegularAction and type(action.operation) is ReturnFileData:
              if action.operand.offset.id == SystemFileIds.UID.value:
                self.uid = struct.unpack(">Q", bytearray(action.operand.data))[0]
              if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value:
                self.firmware_version = FirmwareVersionFile.parse(ConstBitStream(bytearray(action.operand.data)))

        if self.uid and self.firmware_version:
          return True

      if (datetime.now() - start_time).total_seconds() > 2:
        timeout = True
        self.log("Timed out reading node information")

    return False


  def log(self, *msg):
    if self.show_logging: print " ".join(map(str, msg))

  def send_command(self, alp_command):
    data = self.parser.build_serial_frame(alp_command)
    self.dev.write(data)
    self.dev.flush()
    self.log("Sending command of size ", len(data))
    self.log("> " + " ".join(map(lambda b: format(b, "02x"), data)))

  def d7asp_fifo_flush(self, alp_command):
    self.send_command(alp_command)
    flush_done = False
    should_restart_async_read = False
    if self.read_async_active:
      self.log("stopping read thread")
      should_restart_async_read = True
      self.read_async_active = False
      self.read_thread.shutdown = True
      self.read_thread.join()
      self.log("read thread stopped")

    start_time = datetime.now()
    timeout = False
    self.log("flush start of command with tag {}".format(alp_command.tag_id))
    while not flush_done and not timeout:
      data_received = self.dev.read()
      self.log("< " + " ".join(map(lambda b: format(b, "02x"), bytearray(data_received))))
      if len(data_received) > 0:
        (cmds, info) = self.parser.parse(data_received)

        for cmd in cmds:
          if cmd.tag_id == alp_command.tag_id:
            flush_done = True
            if cmd.completed_with_error:
              self.log("Flushing cmd with tag {} done, with error".format(cmd.tag_id))
            else:
              self.log("Flushing cmd with tag {} done, without error".format(cmd.tag_id))
            break

        for error in info["errors"]:
          error["buffer"] = " ".join(["0x{:02x}".format(ord(b)) for b in error["buffer"]])
          print error

      if (datetime.now() - start_time).total_seconds() > 2:
        timeout = True
        self.log("Flush timed out, skipping")

    if should_restart_async_read:
      self.start_reading()

  def read(self):
    try:
      data = self.dev.read_all()
      if len(data) > 0:
        self.log("< " + " ".join(map(lambda b: format(b, "02x"), bytearray(data))))
    except serial.SerialException:
      time.sleep(5)
      self.setup_serial_device()
      data = ""
    return self.parser.parse(data)

  def cancel_read(self):
    if self.read_async_active:
      self.read_async_active = False
      self.read_thread.shutdown = True
      self.read_thread.join()

  def start_reading(self):
    self.read_async_active = True
    self.read_thread = Thread(target=self.read_async)
    self.read_thread.daemon = True
    self.read_thread.start()

  def read_async(self):
    self.log("starting read thread")

    while self.read_async_active:
      data_received = self.dev.read()
      if len(data_received) > 0:
        self.log("< " + " ".join(map(lambda b: format(b, "02x"), bytearray(data_received))))
        (cmds, info) = self.parser.parse(data_received)
        for error in info["errors"]:
          error["buffer"] = " ".join(["0x{:02x}".format(ord(b)) for b in error["buffer"]])
          self.log("Parser error: {}".format(error))

        for cmd in cmds:
          if self.receive_callback != None:
            self.receive_callback(cmd)

    self.log("end read thread")
Exemple #7
0
class Modem:
    def __init__(self, device, baudrate,
                 unsolicited_response_received_callback):
        self.log = logging.getLogger(__name__)
        self.parser = Parser()
        self.config = {"device": device, "baudrate": baudrate}

        self.uid = None
        self.firmware_version = None
        self._sync_execution_response_cmds = []
        self._sync_execution_tag_id = None
        self._sync_execution_completed = False
        self._unsolicited_responses_received = []
        self._read_async_active = False
        self.unsolicited_response_received_callback = unsolicited_response_received_callback

        connected = self._connect_serial_modem()
        if connected:
            self.log.info(
                "connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}"
                .format(self.config["device"], self.uid,
                        self.firmware_version.d7ap_version,
                        self.firmware_version.application_name,
                        self.firmware_version.git_sha1))
        else:
            raise ModemConnectionError

    def _connect_serial_modem(self):
        self.dev = serial.Serial(
            port=self.config["device"],
            baudrate=self.config["baudrate"],
            timeout=None,
        )

        self.dev.flush()  # ignore possible buffered data
        self.start_reading()
        read_modem_info_action = Command.create_with_read_file_action_system_file(
            UidFile())
        read_modem_info_action.add_action(
            RegularAction(operation=ReadFileData(operand=DataRequest(
                offset=Offset(id=FirmwareVersionFile().id,
                              offset=0),  # TODO offset size
                length=FirmwareVersionFile().length))))

        resp_cmd = self.execute_command(read_modem_info_action,
                                        timeout_seconds=60)

        if len(resp_cmd) == 0:
            self.log.warning("Timed out reading node information")
            return False

        for action in resp_cmd[0].actions:
            if type(action) is RegularAction and type(
                    action.operation) is ReturnFileData:
                if action.operand.offset.id == SystemFileIds.UID.value:
                    self.uid = '{:x}'.format(
                        struct.unpack(">Q", bytearray(action.operand.data))[0])
                if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value:
                    self.firmware_version = FirmwareVersionFile.parse(
                        ConstBitStream(bytearray(action.operand.data)))

        if self.uid and self.firmware_version:
            return True

        return False

    def execute_command_async(self, alp_command):
        self.execute_command(alp_command, timeout_seconds=0)

    def execute_command(self, alp_command, timeout_seconds=10):
        data = self.parser.build_serial_frame(alp_command)
        self._sync_execution_response_cmds = []
        self._sync_execution_tag_id = None
        self._sync_execution_completed = False
        if (timeout_seconds > 0):
            assert self._sync_execution_tag_id is None
            self._sync_execution_tag_id = alp_command.tag_id

        self.dev.write(data)
        self.dev.flush()
        self.log.info("Sending command of size %s" % len(data))
        self.log.debug("> " + " ".join(map(lambda b: format(b, "02x"), data)))
        if timeout_seconds == 0:
            return []

        self.log.info(
            "Waiting for response (max {} s)".format(timeout_seconds))
        start_time = datetime.now()
        while not self._sync_execution_completed and (
                datetime.now() - start_time).total_seconds() < timeout_seconds:
            time.sleep(0.05)

        if not self._sync_execution_completed:
            self.log.info("Command timeout (tag {})".format(
                alp_command.tag_id))
            return []

        return self._sync_execution_response_cmds

    def start_reading(self):
        self._read_async_active = True
        self.read_thread = Thread(target=self._read_async)
        self.read_thread.daemon = True
        self.read_thread.start()

    def stop_reading(self):
        self._read_async_active = False
        self.dev.cancel_read()
        self.read_thread.join()

    def get_unsolicited_responses_received(self):
        return self._unsolicited_responses_received

    def clear_unsolicited_responses_received(self):
        self._unsolicited_responses_received = []

    def _read_async(self):
        self.log.info("starting read thread")
        data_received = bytearray()
        while self._read_async_active:
            try:
                data_received = self.dev.read()
            except serial.SerialException:
                self.log.warning(
                    "SerialException received, trying to reconnect")
                self.dev.close()
                time.sleep(5)
                self._connect_serial_modem()

            if len(data_received) > 0:
                self.log.debug("< " + " ".join(
                    map(lambda b: format(b, "02x"), bytearray(data_received))))
                (cmds, info) = self.parser.parse(data_received)
                for error in info["errors"]:
                    error["buffer"] = " ".join(
                        map(lambda b: format(b, "02x"),
                            bytearray(data_received)))
                    self.log.warning("Parser error: {}".format(error))

                for cmd in cmds:
                    if self._sync_execution_tag_id == cmd.tag_id:
                        self.log.info("Received response for sync execution")
                        self._sync_execution_response_cmds.append(cmd)
                        if cmd.execution_completed:
                            self.log.info("cmd with tag {} done".format(
                                cmd.tag_id))
                            self._sync_execution_completed = True
                        else:
                            self.log.info(
                                "cmd with tag {} not done yet, expecting more responses"
                                .format(cmd.tag_id))

                    elif self.unsolicited_response_received_callback != None:
                        self.unsolicited_response_received_callback(cmd)
                    else:
                        self.log.info(
                            "Received a response which was not requested synchronously or no async callback provided"
                        )
                        self._unsolicited_responses_received.append(cmd)

        self.log.info("end read thread")
import fileinput

from d7a.serial_console_interface.parser import Parser

parser = Parser()
for hexstring in fileinput.input():
  hexstring = hexstring.strip().replace(' ', '')
  cmds, info = parser.parse(bytearray(hexstring.decode("hex")))
  for cmd in cmds:
    print cmd

  print info
Exemple #9
0
#!/usr/bin/env python

from d7a.serial_console_interface.parser import Parser
from pprint import pprint

cmd = [
    0x20,  # action=32/ReturnFileData
    0x40,  # File ID
    0x00,  # offset
    0x04,  # length
    0x00,
    0xf3,
    0x00,
    0x00  # data
]

frame = [
    0xC0,  # interface sync byte
    0,  # interface version
    len(cmd),  # ALP cmd length
] + cmd

(cmds, info) = Parser().parse(frame)

pprint(cmds[0].as_dict())

print(["0x{:02x}".format(b) for b in bytearray(cmds[0])])
Exemple #10
0
 def setUp(self):
     self.parser = Parser()
Exemple #11
0
 def setUp(self):
     self.parser = Parser()
class Modem:
    def __init__(self, device, baudrate, receive_callback, show_logging=True):
        self.show_logging = show_logging
        self.parser = Parser()
        self.config = {"device": device, "baudrate": baudrate}

        self.uid = None
        self.firmware_version = None
        connected = self._connect_serial_modem()
        if connected:
            print(
                "connected to {}, node UID {} running D7AP v{}, application \"{}\" with git sha1 {}"
                .format(self.config["device"], self.uid,
                        self.firmware_version.d7ap_version,
                        self.firmware_version.application_name,
                        self.firmware_version.git_sha1))
        else:
            raise ModemConnectionError

        self.read_async_active = False
        self.receive_callback = receive_callback

    def _connect_serial_modem(self):
        self.dev = serial.Serial(
            port=self.config["device"],
            baudrate=self.config["baudrate"],
            timeout=0.5,
        )

        read_modem_info_action = Command.create_with_read_file_action_system_file(
            UidFile())
        read_modem_info_action.add_action(
            RegularAction(operation=ReadFileData(operand=DataRequest(
                offset=Offset(id=FirmwareVersionFile().id,
                              offset=0),  # TODO offset size
                length=FirmwareVersionFile().length))))

        self.send_command(read_modem_info_action)

        # read thread not yet running here, read sync
        start_time = datetime.now()
        timeout = False
        while not timeout:
            commands, info = self.read()
            for command in commands:
                for action in command.actions:
                    if type(action) is RegularAction and type(
                            action.operation) is ReturnFileData:
                        if action.operand.offset.id == SystemFileIds.UID.value:
                            self.uid = '{:x}'.format(
                                struct.unpack(">Q",
                                              bytearray(
                                                  action.operand.data))[0])
                        if action.operand.offset.id == SystemFileIds.FIRMWARE_VERSION.value:
                            self.firmware_version = FirmwareVersionFile.parse(
                                ConstBitStream(bytearray(action.operand.data)))

                if self.uid and self.firmware_version:
                    return True

            if (datetime.now() - start_time).total_seconds() > 2:
                timeout = True
                self.log("Timed out reading node information")

        return False

    def log(self, *msg):
        if self.show_logging: print " ".join(map(str, msg))

    def send_command(self, alp_command):
        data = self.parser.build_serial_frame(alp_command)
        self.dev.write(data)
        self.dev.flush()
        self.log("Sending command of size ", len(data))
        self.log("> " + " ".join(map(lambda b: format(b, "02x"), data)))

    def d7asp_fifo_flush(self, alp_command):
        self.send_command(alp_command)
        flush_done = False
        should_restart_async_read = False
        if self.read_async_active:
            self.log("stopping read thread")
            should_restart_async_read = True
            self.read_async_active = False
            self.read_thread.shutdown = True
            self.read_thread.join()
            self.log("read thread stopped")

        start_time = datetime.now()
        timeout = False
        self.log("flush start of command with tag {}".format(
            alp_command.tag_id))
        while not flush_done and not timeout:
            data_received = self.dev.read()
            self.log("< " + " ".join(
                map(lambda b: format(b, "02x"), bytearray(data_received))))
            if len(data_received) > 0:
                (cmds, info) = self.parser.parse(data_received)

                for cmd in cmds:
                    self.log(cmd)
                    if cmd.tag_id == alp_command.tag_id and cmd.execution_completed:
                        flush_done = True
                        if cmd.completed_with_error:
                            self.log(
                                "Flushing cmd with tag {} done, with error".
                                format(cmd.tag_id))
                        else:
                            self.log(
                                "Flushing cmd with tag {} done, without error".
                                format(cmd.tag_id))
                        break

                for error in info["errors"]:
                    error["buffer"] = " ".join(
                        ["0x{:02x}".format(ord(b)) for b in error["buffer"]])
                    print error

            if (datetime.now() - start_time).total_seconds() > 10:
                timeout = True
                self.log("Flush timed out, skipping")

        if should_restart_async_read:
            self.start_reading()

    def read(self):
        try:
            data = self.dev.read(self.dev.inWaiting())
            if len(data) > 0:
                self.log(
                    "< " +
                    " ".join(map(lambda b: format(b, "02x"), bytearray(data))))
        except serial.SerialException:
            time.sleep(5)
            self.setup_serial_device()
            data = ""
        return self.parser.parse(data)

    def cancel_read(self):
        if self.read_async_active:
            self.read_async_active = False
            self.read_thread.shutdown = True
            self.read_thread.join()

    def start_reading(self):
        self.read_async_active = True
        self.read_thread = Thread(target=self.read_async)
        self.read_thread.daemon = True
        self.read_thread.start()

    def read_async(self):
        self.log("starting read thread")
        while self.read_async_active:
            data_received = self.dev.read()
            if len(data_received) > 0:
                self.log("< " + " ".join(
                    map(lambda b: format(b, "02x"), bytearray(data_received))))
                (cmds, info) = self.parser.parse(data_received)
                for error in info["errors"]:
                    error["buffer"] = " ".join(
                        ["0x{:02x}".format(ord(b)) for b in error["buffer"]])
                    self.log("Parser error: {}".format(error))

                for cmd in cmds:
                    if self.receive_callback != None:
                        self.receive_callback(cmd)

        self.log("end read thread")
Exemple #13
0
 def __init__(self, serial_device, serial_rate):
     self.parser = Parser()
     self.setup_serial_device(serial_device, serial_rate)
Exemple #14
0
class Modem:
    def __init__(self, serial_device, serial_rate):
        self.parser = Parser()
        self.setup_serial_device(serial_device, serial_rate)

    def setup_serial_device(self, serial_device, serial_rate):
        self.dev = serial.Serial(
            port=serial_device,
            baudrate=serial_rate,
            timeout=0.5,
        )

        self.uid = self.read_uid()
        print("connected to {}, node UID {}".format(serial_device,
                                                    hex(self.uid)))

    def read_uid(self):
        self.send_command(
            Command.create_with_read_file_action_system_file(UidFile()))
        while True:  # TODO timeout
            commands, info = self.read()
            for command in commands:
                for action in command.actions:
                    if type(action) is RegularAction \
                        and type(action.operation) is ReturnFileData \
                        and action.operand.offset.id == SystemFileIds.UID:
                        return struct.unpack(">Q",
                                             bytearray(action.operand.data))[0]

    def log(self, *msg):
        pass  # print " ".join(map(str, msg))

    def send_command(self, alp_command):
        data = self.parser.build_serial_frame(alp_command)
        self.dev.write(data)
        self.dev.flushOutput()
        self.log("Sending command of size", len(data))

    def d7asp_fifo_flush(self, alp_command):
        self.send_command(alp_command)
        flush_done = False
        start_time = datetime.now()
        timeout = False
        while not flush_done and not timeout:
            data_received = self.dev.read()
            if len(data_received) > 0:
                (cmds, info) = self.parser.parse(data_received)

                for cmd in cmds:
                    if cmd.flush_result != None:
                        flush_done = True
                        self.log(
                            "Flushing fifo {} done, success_bitmap={}".format(
                                cmd.flush_result.operand.fifo_token,
                                cmd.flush_result.operand.success_bitmap))
                        break

                for error in info["errors"]:
                    error["buffer"] = " ".join(
                        ["0x{:02x}".format(ord(b)) for b in error["buffer"]])
                    print error

            if (datetime.now() - start_time).total_seconds() > 2:
                timeout = True
                self.log("Flush timed out, skipping")

    def read(self):
        # self.log("Bytes in serial buffer: {}".format(self.dev.inWaiting()))
        data_received = self.dev.read_all()
        return self.parser.parse(data_received)

    def cancel_read(self):
        self.stop_reading = True

    def read_async(self):
        self.stop_reading = False
        while not self.stop_reading:
            data_received = self.dev.read()
            if len(data_received) > 0:
                (cmds, info) = self.parser.parse(data_received)
                for error in info["errors"]:
                    error["buffer"] = " ".join(
                        ["0x{:02x}".format(ord(b)) for b in error["buffer"]])
                    print error

                for cmd in cmds:
                    yield cmd
Exemple #15
0
class Modem:
  def __init__(self, device, baudrate, show_logging=True):
    self.show_logging = show_logging
    self.parser = Parser()
    self.config = {
      "device"   : device,
      "baudrate" : baudrate
    }
    self.setup_serial_device()

  def setup_serial_device(self):
    self.dev = serial.Serial(
      port     = self.config["device"],
      baudrate = self.config["baudrate"],
      timeout  = 0.5,
    )
    # FIXME: this seems to fail sometimes ?!
    # self.uid = self.read_uid()
    # print("connected to {}, node UID {}".format(serial_device, hex(self.uid)))

  def read_uid(self):
    self.send_command(Command.create_with_read_file_action_system_file(UidFile()))
    while True: # TODO timeout
      commands, info = self.read()
      for command in commands:
        for action in command.actions:
          if type(action) is RegularAction \
              and type(action.operation) is ReturnFileData \
              and action.operand.offset.id == SystemFileIds.UID:
            return struct.unpack(">Q", bytearray(action.operand.data))[0]


  def log(self, *msg):
    if self.show_logging: print " ".join(map(str, msg))

  def send_command(self, alp_command):
    data = self.parser.build_serial_frame(alp_command)
    self.dev.write(data)
    self.dev.flush()
    self.log("Sending command of size", len(data))

  def d7asp_fifo_flush(self, alp_command):
    self.send_command(alp_command)
    flush_done = False
    start_time = datetime.now()
    timeout = False
    self.log("flush start of command with tag {}".format(alp_command.tag_id))
    while not flush_done and not timeout:
      data_received = self.dev.read()
      if len(data_received) > 0:
        (cmds, info) = self.parser.parse(data_received)

        for cmd in cmds:
          if cmd.tag_id == alp_command.tag_id:
            flush_done = True
            if cmd.completed_with_error:
              self.log("Flushing cmd with tag {} done, with error".format(cmd.tag_id))
            else:
              self.log("Flushing cmd with tag {} done, without error".format(cmd.tag_id))
            break

        for error in info["errors"]:
          error["buffer"] = " ".join(["0x{:02x}".format(ord(b)) for b in error["buffer"]])
          print error

      if (datetime.now() - start_time).total_seconds() > 2:
        timeout = True
        self.log("Flush timed out, skipping")

  def read(self):
    try:
      data = self.dev.read_all()
    except serial.SerialException:
      time.sleep(5)
      self.setup_serial_device()
      data = ""
    return self.parser.parse(data)

  def cancel_read(self):
    self.stop_reading = True

  def read_async(self):
    self.stop_reading = False
    while not self.stop_reading:
      data_received = self.dev.read()
      if len(data_received) > 0:
        (cmds, info) = self.parser.parse(data_received)
        for error in info["errors"]:
          error["buffer"] = " ".join(["0x{:02x}".format(ord(b)) for b in error["buffer"]])
          print error

        for cmd in cmds:
          yield cmd
Exemple #16
0
class TestParser(unittest.TestCase):
    def setUp(self):
        self.parser = Parser()

    def test_basic_valid_message(self):
        alp_cmd_bytes = [
            0x20,  # action=32/ReturnFileData
            0x40,  # File ID
            0x00,  # offset
            0x04,  # length
            0x00,
            0xf3,
            0x00,
            0x00  # data
        ]

        frame = [
            0xC0,  # interface sync byte
            0,  # interface version
            len(alp_cmd_bytes),  # ALP cmd length
        ] + alp_cmd_bytes

        (cmds, info) = self.parser.parse(frame)
        self.assertEqual(cmds[0].actions[0].operation.op, 32)
        self.assertEqual(cmds[0].actions[0].operation.operand.length.value, 4)

    def test_bad_identifier(self):
        (cmds, info) = self.parser.parse([
            0x0c,  # that's 0c not c0 ! ;-)
            0x04,
            0x00,
            0x00,
            0x00,
            0x20,
            0x24,
            0x8a,
            0xb6,
            0x00,
            0x52,
            0x0b,
            0x35,
            0x2c,
            0x20,
            0x40,
            0x00,
            0x00
        ])
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 1)

    def test_buffer_skipping(self):
        self.parser.buffer = bytearray(
            [0x10, 0x20, 0x30, 0xc0, 0x10, 0x20, 0x30])
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 3)
        self.assertEquals(self.parser.buffer,
                          bytearray([0xc0, 0x10, 0x20, 0x30]))

    def test_entire_buffer_skipping(self):
        self.parser.buffer = [0x10, 0x20, 0x30, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 6)
        self.assertEquals(self.parser.buffer, bytearray())

    def test_empty_buffer_skipping(self):
        self.parser.buffer = []
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 0)
        self.assertEquals(self.parser.buffer, [])

    def test_buffer_skipping_with_first_item_the_id(self):
        self.parser.buffer = [0xc0, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 4)
        self.assertEquals(self.parser.buffer, bytearray())

    def test_buffer_skipping_with_first_and_second_item_the_id(self):
        self.parser.buffer = bytearray([0xc0, 0xc0, 0x10, 0x20, 0x30])
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 1)
        self.assertEquals(self.parser.buffer,
                          bytearray([0xc0, 0x10, 0x20, 0x30]))

    def test_bad_identifier_with_identifier_in_body(self):
        (cmds, info) = self.parser.parse(
            bytearray([
                0x0c,  # that's 0c not c0 ! ;-)
                0x04,
                0x00,
                0x00,
                0x00,
                0x20,
                0x24,
                0x8a,
                0xc0,
                0x00,
                7,
                0x0b,
                0x35,
                0x2c,
                0x7d,  # ^ here's another one
                0x40,
                0x00,
                0x00
            ]))
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 2)
        self.assertEquals(info["errors"][0]["skipped"], 8)

    def test_partial_command(self):
        alp_action_bytes = bytearray([
            0x20,  # action=32/ReturnFileData
            0x40,  # File ID
            0x00,  # offset
            0x04,  # length
            0x00,
            0xf3,
            0x00,
            0x00  # data
        ])

        (cmds, info) = self.parser.parse(
            bytearray([
                0xc0,  # interface start
                0,
                2 * len(alp_action_bytes
                        )  # expect 2 ALP actions but only one in buffer
            ]) + alp_action_bytes)
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 0)
        self.assertEquals(info["parsed"], 0)

    def test_continue_partial_command(self):
        self.test_partial_command(
        )  # incomplete command, add second ALP action to complete it ...
        (cmds, info) = self.parser.parse(
            bytearray([
                0x20,  # action=32/ReturnFileData
                0x40,  # File ID
                0x00,  # offset
                0x04,  # length
                0x00,
                0xf3,
                0x00,
                0x00  # data
            ]))
        self.assertEquals(len(info["errors"]), 0)
        self.assertEqual(len(cmds[0].actions), 2)

    def test_continue_from_bad_buffer(self):
        self.test_bad_identifier_with_identifier_in_body()  # buffer is bad now
        self.test_basic_valid_message()  # cont. with valid msg

    def test_continue_partial_second_frame(self):
        alp_cmd_bytes = [
            0x20,  # action=32/ReturnFileData
            0x40,  # File ID
            0x00,  # offset
            0x04,  # length
            0x00,
            0xf3,
            0x00,
            0x00  # data
        ]

        frame = [
            0xC0,  # interface sync byte
            0,  # interface version
            len(alp_cmd_bytes),  # ALP cmd length
        ] + alp_cmd_bytes + [
            # second, partial frame
            0xC0,
            0,
            len(alp_cmd_bytes)
        ]

        # first frame should parse
        (cmds, info) = self.parser.parse(frame)
        self.assertEqual(cmds[0].actions[0].operation.op, 32)
        self.assertEqual(cmds[0].actions[0].operation.operand.length.value, 4)

        # and now complete the second frame and check this is parsed as well
        (cmds, info) = self.parser.parse(
            alp_cmd_bytes)  # the missing bytes only, without the frame header
        self.assertEqual(cmds[0].actions[0].operation.op, 32)
        self.assertEqual(cmds[0].actions[0].operation.operand.length.value, 4)
Exemple #17
0
argparser.add_argument("-t", "--type", choices=parser_types, required=True)
argparser.add_argument("-f",
                       "--file-id",
                       help="the ID of the system file to parse",
                       type=int)
argparser.add_argument('data',
                       help="The data to be parsed, input as an hexstring")
args = argparser.parse_args()

hexstring = args.data.strip().replace(' ', '')
data = bytearray(hexstring.decode("hex"))
if args.type == "alp":
    print AlpParser().parse(ConstBitStream(data), len(data))
    exit(0)
if args.type == "serial":
    parser = SerialParser()
if args.type == "fg":
    parser = DllFrameParser(frame_type=FrameType.FOREGROUND)
if args.type == "bg":
    parser = DllFrameParser(frame_type=FrameType.BACKGROUND)
if args.type == "systemfile":
    file = SystemFileIds(args.file_id)
    file_type = SystemFiles().files[file]
    print(file_type.parse(ConstBitStream(data)))
    exit(0)

cmds, info = parser.parse(data)
for cmd in cmds:
    print cmd

print info
Exemple #18
0
class TestParser(unittest.TestCase):
    def setUp(self):
        self.parser = Parser()

    def test_basic_valid_message(self):
        alp_cmd_bytes = [
            0x20,  # action=32/ReturnFileData
            0x40,  # File ID
            0x00,  # offset
            0x04,  # length
            0x00,
            0xF3,
            0x00,
            0x00,  # data
        ]

        frame = [
            0xC0,  # interface sync byte
            0,  # interface version
            len(alp_cmd_bytes),  # ALP cmd length
        ] + alp_cmd_bytes

        (cmds, info) = self.parser.parse(frame)
        self.assertEqual(cmds[0].actions[0].operation.op, 32)
        self.assertEqual(cmds[0].actions[0].operation.operand.length, 4)

    def test_bad_identifier(self):
        (cmds, info) = self.parser.parse(
            [
                0x0C,  # that's 0c not c0 ! ;-)
                0x04,
                0x00,
                0x00,
                0x00,
                0x20,
                0x24,
                0x8A,
                0xB6,
                0x00,
                0x52,
                0x0B,
                0x35,
                0x2C,
                0x20,
                0x40,
                0x00,
                0x00,
            ]
        )
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 1)

    def test_buffer_skipping(self):
        self.parser.buffer = [0x10, 0x20, 0x30, 0xC0, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 3)
        self.assertEquals(self.parser.buffer, [0xC0, 0x10, 0x20, 0x30])

    def test_entire_buffer_skipping(self):
        self.parser.buffer = [0x10, 0x20, 0x30, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 6)
        self.assertEquals(self.parser.buffer, [])

    def test_empty_buffer_skipping(self):
        self.parser.buffer = []
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 0)
        self.assertEquals(self.parser.buffer, [])

    def test_buffer_skipping_with_first_item_the_id(self):
        self.parser.buffer = [0xC0, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 4)
        self.assertEquals(self.parser.buffer, [])

    def test_buffer_skipping_with_first_and_second_item_the_id(self):
        self.parser.buffer = [0xC0, 0xC0, 0x10, 0x20, 0x30]
        skipped = self.parser.skip_bad_buffer_content()
        self.assertEquals(skipped, 1)
        self.assertEquals(self.parser.buffer, [0xC0, 0x10, 0x20, 0x30])

    def test_bad_identifier_with_identifier_in_body(self):
        (cmds, info) = self.parser.parse(
            [
                0x0C,  # that's 0c not c0 ! ;-)
                0x04,
                0x00,
                0x00,
                0x00,
                0x20,
                0x24,
                0x8A,
                0xC0,
                0x00,
                7,
                0x0B,
                0x35,
                0x2C,
                0x7D,  # ^ here's another one
                0x40,
                0x00,
                0x00,
            ]
        )
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 2)
        self.assertEquals(info["errors"][0]["skipped"], 8)

    def test_partial_command(self):
        alp_action_bytes = [
            0x20,  # action=32/ReturnFileData
            0x40,  # File ID
            0x00,  # offset
            0x04,  # length
            0x00,
            0xF3,
            0x00,
            0x00,  # data
        ]

        (cmds, info) = self.parser.parse(
            [0xC0, 0, 2 * len(alp_action_bytes)]  # interface start  # expect 2 ALP actions but only one in buffer
            + alp_action_bytes
        )
        self.assertEquals(len(cmds), 0)
        self.assertEquals(len(info["errors"]), 0)
        self.assertEquals(info["parsed"], 0)

    def test_continue_partial_command(self):
        self.test_partial_command()  # incomplete command, add second ALP action to complete it ...
        (cmds, info) = self.parser.parse(
            [
                0x20,  # action=32/ReturnFileData
                0x40,  # File ID
                0x00,  # offset
                0x04,  # length
                0x00,
                0xF3,
                0x00,
                0x00,  # data
            ]
        )
        self.assertEquals(len(info["errors"]), 0)
        self.assertEqual(len(cmds[0].actions), 2)

    def test_continue_from_bad_buffer(self):
        self.test_bad_identifier_with_identifier_in_body()  # buffer is bad now
        self.test_basic_valid_message()  # cont. with valid msg