Start the FSM.

        Returns:
            boolean: True if FSM reaches the last state or false if the exception or error message was raised

def run(self):
        """Start the FSM.

        Returns:
            boolean: True if FSM reaches the last state or false if the exception or error message was raised

        """
        ctx = FSM.Context(self.name, self.device)
        transition_counter = 0
        timeout = self.timeout
        self.log("{} Start".format(self.name))
        while transition_counter < self.max_transitions:
            transition_counter += 1
            try:
                start_time = time()
                if self.init_pattern is None:
                    ctx.event = self.ctrl.expect(self.events, searchwindowsize=self.searchwindowsize, timeout=timeout)
                else:
                    self.log("INIT_PATTERN={}".format(pattern_to_str(self.init_pattern)))
                    try:
                        ctx.event = self.events.index(self.init_pattern)
                    except ValueError:
                        self.log("INIT_PATTERN unknown.")
                        continue
                    finally:
                        self.init_pattern = None

                finish_time = time() - start_time
                key = (ctx.event, ctx.state)
                ctx.pattern = self.events[ctx.event]

                if key in self.transition_table:
                    transition = self.transition_table[key]
                    next_state, action_instance, next_timeout = transition
                    self.log("E={},S={},T={},RT={:.2f}".format(ctx.event, ctx.state, timeout, finish_time))
                    if callable(action_instance) and not isclass(action_instance):
                        if not action_instance(ctx):
                            self.log("Error: {}".format(ctx.msg))
                            return False
                    elif isinstance(action_instance, Exception):
                        self.log("A=Exception {}".format(action_instance))
                        raise action_instance
                    elif action_instance is None:
                        self.log("A=None")
                    else:
                        self.log("FSM Action is not callable: {}".format(str(action_instance)))
                        raise RuntimeWarning("FSM Action is not callable")

                    if next_timeout != 0:  # no change if set to 0
                        timeout = next_timeout
                    ctx.state = next_state
                    self.log("NS={},NT={}".format(next_state, timeout))

                else:
                    self.log("Unknown transition: EVENT={},STATE={}".format(ctx.event, ctx.state))
                    continue

            except EOF:
                raise ConnectionError("Session closed unexpectedly", self.ctrl.hostname)

            if ctx.finished or next_state == -1:
                self.log("{} Stop at E={},S={}".format(self.name, ctx.event, ctx.state))
                return True

        # check while else if even exists
        self.log("FSM looped. Exiting")
        return False