def process_switch(self, name=None, state=1, logical=False, num=None,
                       obj=None, debounced=True):
        """Processes a new switch state change.

        Args:
            name: The string name of the switch. This is optional if you specify
                the switch via the 'num' or 'obj' parameters.
            state: Boolean or int of state of the switch you're processing,
                True/1 is active, False/0 is inactive.
            logical: Boolean which specifies whether the 'state' argument
                represents the "physical" or "logical" state of the switch. If
                True, a 1 means this switch is active and a 0 means it's
                inactive, regardless of the NC/NO configuration of the switch.
                If False, then the state paramenter passed will be inverted if
                the switch is configured to be an 'NC' type. Typically the
                hardware will send switch states in their raw (logical=False)
                states, but other interfaces like the keyboard and OSC will use
                logical=True.
            num: The hardware number of the switch.
            obj: The switch object.
            debounced: Whether or not the update for the switch you're sending
                has been debounced or not. Default is True

        Note that there are three different paramter options to specify the
        switch: 'name', 'num', and 'obj'. You only need to pass one of them.

        This is the method that is called by the platform driver whenever a
        switch changes state. It's also used by the "other" modules that
        activate switches, including the keyboard and OSC interfaces.

        State 0 means the switch changed from active to inactive, and 1 means
        it changed from inactive to active. (The hardware & platform code
        handles NC versus NO switches and translates them to 'active' versus
        'inactive'.)

        """

        self.log.debug("Processing switch. Name: %s, state: %s, logical: %s,"
                       "num: %s, obj: %s, debounced: %s", name, state, logical,
                       num, obj, debounced)

        # Find the switch name

        if num is not None:  # can't be 'if num:` in case the num is 0.
            for switch in self.machine.switches:
                if switch.number == num:
                    name = switch.name
                    obj = switch
                    break

        elif obj:
            name = obj.name

        elif name:

            try:
                obj = self.machine.switches[name]
            except KeyError:
                self.log.warning("Cannot process switch '%s' as this is not a"
                                 "valid switch name.", name)
                return

            name = obj.name  # switches this to the name MPF wants to use

        if not obj:
            self.log.warning("Received a state change from non-configured "
                             "switch. Number: %s, Name: %s", num, name)
            return

        # We need int, but this lets it come in as boolean also
        if state:
            state = 1
        else:
            state = 0

        # flip the logical & physical states for NC switches
        hw_state = state

        if obj.invert:
            if logical:  # NC + logical means hw_state is opposite of state
                hw_state ^= 1
            else:
                # NC w/o logical (i.e. hardware state was sent) means logical
                # state is the opposite
                state ^= 1

        # If this update is not debounced, only proceed if this switch is
        # configured to not be debounced.

        if not debounced:
            if obj.config['debounce']:
                return

        # Update the hardware state since we always want this to match real hw
        obj.hw_state = hw_state

        # if the switch is active, check to see if it's recycle_time has passed
        if state and not self._check_recycle_time(obj, state):
            return

        obj.state = state  # update the switch device

        if state:
            # update the switch's next recycle clear time
            obj.recycle_clear_tick = Timing.tick + obj.recycle_ticks

        # if the switch is already in this state, then abort
        if self.switches[name]['state'] == state:

            if not obj.recycle_ticks:
                self.log.info("Received duplicate switch state, which means "
                              "this switch had some non-debounced state changes. This "
                              "could be nothing, but if it happens a lot it could "
                              "indicate noise or interference on the line. Switch: %s",
                              name)

            return

        self.log.info("<<<<< switch: %s, State:%s >>>>>", name, state)

        # Update the switch controller's logical state for this switch
        self.set_state(name, state)

        # Combine name & state so we can look it up
        switch_key = str(name) + '-' + str(state)

        # Do we have any registered handlers for this switch/state combo?
        if switch_key in self.registered_switches:
            for entry in self.registered_switches[switch_key]:  # generator?
                # Found an entry.

                if entry['ms']:
                    # This entry is for a timed switch, so add it to our
                    # active timed switch list
                    key = time.time() + (1000.0 / entry['ms'])
                    value = {'switch_action': str(name) + '-' + str(state),
                             'callback': entry['callback'],
                             'switch_name': name,
                             'state': state,
                             'ms': entry['ms'],
                             'removed': False,
                             'return_info': entry['return_info'],
                             'callback_kwargs': entry['callback_kwargs']}
                    self.active_timed_switches[key].append(value)
                    self.log.debug(
                        "Found timed switch handler for k/v %s / %s",
                        key, value)
                else:
                    # This entry doesn't have a timed delay, so do the action
                    # now
                    if entry['return_info']:

                        entry['callback'](switch_name=name, state=state, ms=0,
                                          **entry['callback_kwargs'])
                    else:
                        entry['callback'](**entry['callback_kwargs'])

                        # todo need to add args and kwargs support to callback

        # now check if the opposite state is in the active timed switches list
        # if so, remove it
        for k, v, in self.active_timed_switches.items():
            # using items() instead of iteritems() since we might want to
            # delete while iterating

            for item in v:
                if item['switch_action'] == str(name) + '-' + str(state ^ 1):
                    # ^1 in above line invertes the state
                    if self.active_timed_switches[k]:
                        del self.active_timed_switches[k]

        for monitor in self.monitors:
            monitor(name, state)

        self._post_switch_events(name, state)
dataset/ETHPy150Open missionpinball/mpf/mpf/system/switch_controller.py/SwitchController.process_switch/swapped operands of `/`