def configure(self, config=None): """Performs the actual configuration of the ball device based on the dictionary that was passed to it. Args: config: Python dictionary which holds the configuration settings. """ # Merge in any new changes that were just passed if config: self.config.update(config) self.log.debug("Configuring device with: %s", self.config) # convert delay strings to ms ints if self.config['exit_count_delay']: self.config['exit_count_delay'] = \ Timing.string_to_ms(self.config['exit_count_delay']) if self.config['entrance_count_delay']: self.config['entrance_count_delay'] = \ Timing.string_to_ms(self.config['entrance_count_delay']) # Register for events # Look for eject requests for this device self.machine.events.add_handler('balldevice_' + self.name + '_ball_eject_request', self.eject)
def configure(self, config=None): """Performs the actual configuration of the ball device based on the dictionary that was passed to it. Args: config: Python dictionary which holds the configuration settings. """ # Merge in any new changes that were just passed if config: self.config.update(config) self.log.debug("Configuring device with: %s", self.config) # convert delay strings to ms ints if self.config['exit_count_delay']: self.config['exit_count_delay'] = \ Timing.string_to_ms(self.config['exit_count_delay']) if self.config['entrance_count_delay']: self.config['entrance_count_delay'] = \ Timing.string_to_ms(self.config['entrance_count_delay']) # Register for events # Look for eject requests for this device self.machine.events.add_handler( 'balldevice_' + self.name + '_ball_eject_request', self.eject)
def __init__(self, machine, name, config): self.log = logging.getLogger('HitCounter.' + name) self.log.debug("Creating HitCounter LogicBlock") super(HitCounter, self).__init__(machine, name, config) self.delay = DelayManager() self.num_hits = 0 self.ignore_hits = False if 'trigger_events' not in self.config: return # Not much point to continue here else: self.config['trigger_events'] = self.machine.string_to_list( self.config['trigger_events']) if 'event_when_hit' not in self.config: self.config['event_when_hit'] = ('eventtrigger_' + self.name + '_hit') if 'hits_to_complete' not in self.config: self.config['hits_to_complete'] = 1 if 'multiple_hit_window' not in self.config: self.config['multiple_hit_window'] = None else: self.config['multiple_hit_window'] = Timing.string_to_ms( self.config['multiple_hit_window']) if 'settle_time' not in self.config: self.config['settle_time'] = None else: self.config['settle_time'] = Timing.string_to_ms( self.config['settle_time'])
def _initialize_switches(self): self.update_switches_from_hw() for switch in self.machine.switches: # Populate self.switches self.set_state(switch.name, switch.state, reset_time=True) # Populate self.registered_switches self.registered_switches[switch.name + '-0'] = list() self.registered_switches[switch.name + '-1'] = list() if self.machine.config['mpf']['auto_create_switch_events']: switch.activation_events.add( self.machine.config['mpf']['switch_event_active'].replace( '%', switch.name)) switch.deactivation_events.add( self.machine.config['mpf'][ 'switch_event_inactive'].replace( '%', switch.name)) if 'activation_events' in switch.config: for event in Config.string_to_lowercase_list( switch.config['activation_events']): if "|" in event: ev_name, ev_time = event.split("|") self.add_switch_handler( switch_name=switch.name, callback=self.machine.events.post, state=1, ms=Timing.string_to_ms(ev_time), callback_kwargs={'event': ev_name} ) else: switch.activation_events.add(event) if 'deactivation_events' in switch.config: for event in Config.string_to_lowercase_list( switch.config['deactivation_events']): if "|" in event: ev_name, ev_time = event.split("|") self.add_switch_handler( switch_name=switch.name, callback=self.machine.events.post, state=0, ms=Timing.string_to_ms(ev_time), callback_kwargs={'event': ev_name} ) else: switch.deactivation_events.add(event)
def _initialize_switches(self): self.update_switches_from_hw() for switch in self.machine.switches: # Populate self.switches self.set_state(switch.name, switch.state, reset_time=True) # Populate self.registered_switches self.registered_switches[switch.name + '-0'] = list() self.registered_switches[switch.name + '-1'] = list() if self.machine.config['mpf']['auto_create_switch_events']: switch.activation_events.add( self.machine.config['mpf']['switch_event_active'].replace( '%', switch.name)) switch.deactivation_events.add( self.machine.config['mpf'] ['switch_event_inactive'].replace('%', switch.name)) if 'activation_events' in switch.config: for event in Util.string_to_lowercase_list( switch.config['activation_events']): if "|" in event: ev_name, ev_time = event.split("|") self.add_switch_handler( switch_name=switch.name, callback=self.machine.events.post, state=1, ms=Timing.string_to_ms(ev_time), callback_kwargs={'event': ev_name}) else: switch.activation_events.add(event) if 'deactivation_events' in switch.config: for event in Util.string_to_lowercase_list( switch.config['deactivation_events']): if "|" in event: ev_name, ev_time = event.split("|") self.add_switch_handler( switch_name=switch.name, callback=self.machine.events.post, state=0, ms=Timing.string_to_ms(ev_time), callback_kwargs={'event': ev_name}) else: switch.deactivation_events.add(event)
def __init__(self, machine, name, config, priority): """SequenceShot is where you need certain switches to be hit in the right order, possibly within a time limit. Subclass of `Shot` Args: machine: The MachineController object name: String name of this shot. config: Dictionary that holds the configuration for this shot. """ super(SequenceShot, self).__init__(machine, name, config, priority) self.delay = DelayManager() self.progress_index = 0 """Tracks how far along through this sequence the current shot is.""" # convert our switches config to a list if 'switches' in self.config: self.config['switches'] = \ Config.string_to_list(self.config['switches']) # convert our timout to ms if 'time' in self.config: self.config['time'] = Timing.string_to_ms(self.config['time']) else: self.config['time'] = 0 self.active_delay = False self.enable()
def _do_step(self): this_step = self.step_list[self.current_step] self.log.debug("Switch: %s, Action: %s", this_step['switch'], this_step['action']) # send this step's switches if this_step['action'] == 'activate': self.machine.switch_controller.process_switch(this_step['switch'], state=1, logical=True) elif this_step['action'] == 'deactivate': self.machine.switch_controller.process_switch(this_step['switch'], state=0, logical=True) elif this_step['action'] == 'hit': self._hit(this_step['switch']) # inc counter if self.current_step < len(self.step_list) - 1: self.current_step += 1 # schedule next step self.delay.add(name='switch_player_next_step', ms=Timing.string_to_ms( self.step_list[self.current_step]['time']), callback=self._do_step)
def __init__(self, machine, name, config, collection=None): self.log = logging.getLogger('Diverter.' + name) super(Diverter, self).__init__(machine, name, config, collection) self.delay = DelayManager() # configure defaults: if 'type' not in self.config: self.config['type'] = 'pulse' # default to pulse to not fry coils if 'timeout' not in self.config: self.config['timeout'] = 0 if 'activation_switch' not in self.config: self.config['activation_switch'] = None if 'disable_switch' not in self.config: self.config['disable_switch'] = None if 'target_when_enabled' not in self.config: self.config['target_when_enabled'] = None # todo if 'target_when_disabled' not in self.config: self.config['target_when_disabled'] = None # todo # convert the timeout to ms self.config['timeout'] = Timing.string_to_ms(self.config['timeout']) # register for events for event in self.config['enable_events']: self.machine.events.add_handler(event, self.enable) for event in self.config['disable_events']: self.machine.events.add_handler(event, self.disable)
def _do_step(self): this_step = self.step_list[self.current_step] self.log.info("Switch: %s, Action: %s", this_step['switch'], this_step['action']) # send this step's switches if this_step['action'] == 'activate': self.machine.switch_controller.process_switch( this_step['switch'], state=1, logical=True) elif this_step['action'] == 'deactivate': self.machine.switch_controller.process_switch( this_step['switch'], state=0, logical=True) elif this_step['action'] == 'hit': self._hit(this_step['switch']) # inc counter if self.current_step < len(self.step_list)-1: self.current_step += 1 # schedule next step self.delay.add(name='switch_player_next_step', ms=Timing.string_to_ms(self.step_list[self.current_step]['time']), callback=self._do_step)
def _create_events(self, ev_name, ev_type, delay, callback): self.log.debug("Creating %s_event handler for event '%s' with delay " "'%s'", ev_type, ev_name, delay) self.machine.events.add_handler(event=ev_name, handler=self._action_event_handler, callback=callback, ms_delay=Timing.string_to_ms(delay))
def _start_event_callback(self): if ('time' in self.step_list[self.current_step] and self.step_list[self.current_step]['time'] > 0): self.delay.add(name='switch_player_next_step', ms=Timing.string_to_ms(self.step_list[self.current_step]['time']), callback=self._do_step)
def _start_event_callback(self): if ('time' in self.step_list[self.current_step] and self.step_list[self.current_step]['time'] > 0): self.delay.add(name='switch_player_next_step', ms=Timing.string_to_ms( self.step_list[self.current_step]['time']), callback=self._do_step)
def _create_events(self, ev_name, ev_type, delay, callback): self.log.debug( "Creating %s_event handler for event '%s' with delay " "'%s'", ev_type, ev_name, delay) self.machine.events.add_handler(event=ev_name, handler=self._action_event_handler, callback=callback, ms_delay=Timing.string_to_ms(delay))
def _start_event_callback(self): if "time" in self.step_list[self.current_step] and self.step_list[self.current_step]["time"] > 0: self.delay.add( name="switch_player_next_step", ms=Timing.string_to_ms(self.step_list[self.current_step]["time"]), callback=self._do_step, )
def configure(self): """Configures the shot.""" # convert our switches config to a list if 'Switches' in self.config: self.config['Switches'] = \ self.machine.string_to_list(self.config['Switches']) # convert our timout to ms if 'Time' in self.config: self.config['Time'] = Timing.string_to_ms(self.config['Time']) else: self.config['Time'] = 0
def schedule_removal(self, removal_time=None): """Schedules this slide to automatically be removed. Args: removal_time: MPF time string of when this slide should be removed. If no time is specified, the slide's existing removal time is used. If the slide has no existing time, the slide will not be removed. """ if removal_time: self.expire_ms = Timing.string_to_ms(removal_time) if self.expire_ms: self.machine.display.delay.add(name=self.name + "_expiration", ms=self.expire_ms, callback=self.remove)
def schedule_removal(self, removal_time=None): """Schedules this slide to automatically be removed. Args: removal_time: MPF time string of when this slide should be removed. If no time is specified, the slide's existing removal time is used. If the slide has no existing time, the slide will not be removed. """ if removal_time: self.expire_ms = Timing.string_to_ms(removal_time) if self.expire_ms: self.machine.display.delay.add(name=self.name + '_expiration', ms=self.expire_ms, callback=self.remove)
def validate_config_item(spec, item='item not in config!@#'): default = 'default required!@#' if '|' in spec: item_type, default = spec.split('|') if type(default) is str and default.lower() == 'none': default = None else: item_type = spec if item == 'item not in config!@#': if default == 'default required!@#': log.error( 'Required setting missing from config file. Run with ' 'verbose logging and look for the last ' 'ConfigProcessor entry above this line to see where ' 'the problem is.') sys.exit() else: item = default if item_type == 'list': return Config.string_to_list(item) elif item_type == 'int': return int(item) elif item_type == 'float': return float(item) elif item_type == 'string': return str(item) elif item_type == 'boolean': if type(item) is bool: return item else: return item.lower() in ('yes', 'true') elif item_type == 'ms': return Timing.string_to_ms(item) elif item_type == 'secs': return Timing.string_to_secs(item) elif item_type == 'list_of_lists': return Config.list_of_lists(item)
def schedule_deactivation(self, time=None): """Schedules a delay to deactivate this diverter. Args: time: The MPF string time of how long you'd like the delay before deactivating the diverter. Default is None which means it uses the 'activation_time' setting configured for this diverter. If there is no 'activation_time' setting and no delay is passed, it will disable the diverter immediately. """ if time is not None: delay = Timing.string_to_ms(time) elif self.config['activation_time']: delay = self.config['activation_time'] if delay: self.delay.add('disable_held_coil', delay, self.disable_held_coil) else: self.disable_held_coil()
def validate_config_item(spec, item='item not in config!@#'): default = 'default required!@#' if '|' in spec: item_type, default = spec.split('|') if type(default) is str and default.lower() == 'none': default = None else: item_type = spec if item == 'item not in config!@#': if default == 'default required!@#': log.error('Required setting missing from config file. Run with ' 'verbose logging and look for the last ' 'ConfigProcessor entry above this line to see where ' 'the problem is.') sys.exit() else: item = default if item_type == 'list': return Config.string_to_list(item) elif item_type == 'int': return int(item) elif item_type == 'float': return float(item) elif item_type == 'string': return str(item) elif item_type == 'boolean': if type(item) is bool: return item else: return item.lower() in ('yes', 'true') elif item_type == 'ms': return Timing.string_to_ms(item) elif item_type == 'secs': return Timing.string_to_secs(item) elif item_type == 'list_of_lists': return Config.list_of_lists(item)
def _do_step(self): this_step = self.step_list[self.current_step] self.log.debug("Switch: %s, Action: %s", this_step["switch"], this_step["action"]) # send this step's switches if this_step["action"] == "activate": self.machine.switch_controller.process_switch(this_step["switch"], state=1, logical=True) elif this_step["action"] == "deactivate": self.machine.switch_controller.process_switch(this_step["switch"], state=0, logical=True) elif this_step["action"] == "hit": self._hit(this_step["switch"]) # inc counter if self.current_step < len(self.step_list) - 1: self.current_step += 1 # schedule next step self.delay.add( name="switch_player_next_step", ms=Timing.string_to_ms(self.step_list[self.current_step]["time"]), callback=self._do_step, )
def validate_item(self, item, validator, validation_failure_info): try: if item.lower() == 'none': item = None except AttributeError: pass if ':' in validator: validator = validator.split(':') # item could be str, list, or list of dicts item = Util.event_config_to_dict(item) return_dict = dict() for k, v in item.iteritems(): return_dict[self.validate_item(k, validator[0], validation_failure_info)] = ( self.validate_item(v, validator[1], validation_failure_info) ) item = return_dict elif '%' in validator: if type(item) is str: try: item = eval(validator.replace('%', "'" + item + "'")) except KeyError: self.validation_error(item, validation_failure_info) else: item = None elif validator == 'str': if item is not None: item = str(item) else: item = None elif validator == 'float': try: item = float(item) except (TypeError, ValueError): # TODO error pass elif validator == 'int': try: item = int(item) except (TypeError, ValueError): # TODO error pass elif validator in ('bool', 'boolean'): if type(item) is str: if item.lower() in ['false', 'f', 'no', 'disable', 'off']: item = False elif not item: item = False else: item = True elif validator == 'ms': item = Timing.string_to_ms(item) elif validator == 'secs': item = Timing.string_to_secs(item) elif validator == 'ticks': item = Timing.string_to_ticks(item) elif validator == 'ticks_int': item = int(Timing.string_to_ticks(item)) else: self.log.error("Invalid Validator '%s' in config spec %s:%s", validator, validation_failure_info[0][0], validation_failure_info[1]) sys.exit() return item
def __init__(self, machine, name, config, collection=None): self.log = logging.getLogger('Diverter.' + name) super(Diverter, self).__init__(machine, name, config, collection) self.delay = DelayManager() # Attributes self.active = False self.enabled = False # configure defaults: if 'type' not in self.config: self.config['type'] = 'pulse' # default to pulse to not fry coils if 'activation_time' not in self.config: self.config['activation_time'] = 0 if 'activation_switches' in self.config: self.config['activation_switches'] = Config.string_to_list( self.config['activation_switches']) else: self.config['activation_switches'] = list() if 'disable_switches' in self.config: self.config['disable_switches'] = Config.string_to_list( self.config['disable_switches']) else: self.config['disable_switches'] = list() if 'deactivation_switches' in self.config: self.config['deactivation_switches'] = Config.string_to_list( self.config['deactivation_switches']) else: self.config['deactivation_switches'] = list() if 'activation_coil' in self.config: self.config['activation_coil'] = ( self.machine.coils[self.config['activation_coil']]) if 'deactivation_coil' in self.config: self.config['deactivation_coil'] = ( self.machine.coils[self.config['deactivation_coil']]) else: self.config['deactivation_coil'] = None if 'targets_when_active' in self.config: self.config['targets_when_active'] = Config.string_to_list( self.config['targets_when_active']) else: self.config['targets_when_active'] = ['playfield'] if 'targets_when_inactive' in self.config: self.config['targets_when_inactive'] = Config.string_to_list( self.config['targets_when_inactive']) else: self.config['targets_when_inactive'] = ['playfield'] if 'feeder_devices' in self.config: self.config['feeder_devices'] = Config.string_to_list( self.config['feeder_devices']) else: self.config['feeder_devices'] = list() # Create a list of ball device objects when active and inactive. We need # this because ball eject attempts pass the target device as an object # rather than by name. self.config['active_objects'] = list() self.config['inactive_objects'] = list() for target_device in self.config['targets_when_active']: if target_device == 'playfield': self.config['active_objects'].append('playfield') else: self.config['active_objects'].append( self.machine.balldevices[target_device]) for target_device in self.config['targets_when_inactive']: if target_device == 'playfield': self.config['inactive_objects'].append('playfield') else: self.config['inactive_objects'].append( self.machine.balldevices[target_device]) # convert the activation_time to ms self.config['activation_time'] = Timing.string_to_ms(self.config['activation_time']) # register for events for event in self.config['enable_events']: self.machine.events.add_handler(event, self.enable) for event in self.config['disable_events']: self.machine.events.add_handler(event, self.disable) # register for feeder device eject events for feeder_device in self.config['feeder_devices']: self.machine.events.add_handler('balldevice_' + feeder_device + '_ball_eject_attempt', self._feeder_eject_attempt) # register for deactivation switches for switch in self.config['deactivation_switches']: self.machine.switch_controller.add_switch_handler( switch, self.deactivate) # register for disable switches: for switch in self.config['disable_switches']: self.machine.switch_controller.add_switch_handler( switch, self.disable)
def preprocess_settings(self, settings, base_priority=0): """Takes an unstructured list of SlidePlayer settings and processed them so they can be displayed. Args: settings: A list of dictionary of SlidePlayer settings for a slide. base_priority: An integer that will be added to slide's priority from the config settings. Returns: A python list with all the settings in the right places. This method does a bunch of things, like making sure all the needed values are there, and moving certain things to the first and last elements when there are multiple elements used on one slide. (For example, if one of the elements wants to clear the slide, it has to happen first. If there's a transition, it has to happen last after the slide is built, etc. The returned settings list can be safely called with the by display() with the preprocessed=True flag. """ # This is a stupid band-aid because when modes load their slideplayer # settings are already processed. I don't know why though, but I don't # have time to track it down now. $50 to anyone who figures out why!!! # Settings can be a list of dicts or just a dict. (Preprocessing is what # turns a dict into a list, though I don't know how sometimes items are # getting the preprocessed entry in their dict but they're not a list??? # todo if type(settings) is list and 'preprocessed' in settings[0]: return settings elif type(settings) is dict and 'preprocessed' in settings: return [settings] processed_settings = list() if type(settings) is dict: settings = [settings] last_settings = dict() first_settings = dict() # Drop this key into the settings so we know they've been preprocessed. first_settings['preprocessed'] = True for element in settings: # Create a slide name based on the event name if one isn't specified if 'slide_name' in element: first_settings['slide_name'] = element.pop('slide_name') if 'removal_key' in element: first_settings['removal_key'] = element.pop('removal_key') # If the config doesn't specify whether this slide should be made # active when this event is called, set a default value of True if 'slide_priority' in element: first_settings['slide_priority'] = ( element.pop('slide_priority') + base_priority) # If a 'clear_slide' setting isn't specified, set a default of True if 'clear_slide' in element: first_settings['clear_slide'] = element.pop('clear_slide') # If a 'persist_slide' setting isn't specified, set default of False if 'persist_slide' in element: first_settings['persist_slide'] = element.pop('persist_slide') if 'display' in element: first_settings['display'] = element.pop('display') if 'transition' in element: last_settings['transition'] = element.pop('transition') if 'name' not in element: element['name'] = None if 'expire' in element: first_settings['expire'] = Timing.string_to_ms( element.pop('expire')) else: first_settings['expire'] = 0 processed_settings.append(element) if 'slide_priority' not in first_settings: first_settings['slide_priority'] = base_priority if 'removal_key' not in first_settings: first_settings['removal_key'] = None # Now add back in the items that need to be in the first element processed_settings[0].update(first_settings) # And add the settings we need to the last entry processed_settings[-1].update(last_settings) return processed_settings
def validate_config_item(spec, item='item not in config!@#'): try: if item.lower() == 'none': item = None except AttributeError: pass default = 'default required!@#' if '|' in spec: item_type, default = spec.split('|') if type(default) is str and default.lower() == 'none': default = None else: item_type = spec if item == 'item not in config!@#': if default == 'default required!@#': log.error('Required setting missing from config file. Run with ' 'verbose logging and look for the last ' 'ConfigProcessor entry above this line to see where ' 'the problem is.') sys.exit() else: item = default if item_type == 'list': return Util.string_to_list(item) if item_type == 'list_of_dicts': if type(item) is list: return item elif type(item) is dict: return [item] elif item_type == 'set': return set(Util.string_to_list(item)) elif item_type == 'dict': if type(item) is dict or type(item) is CaseInsensitiveDict: return item elif not default: return dict() else: log.error('Config error. "%s" is not a dictionary', item) sys.exit() elif item_type == 'int': try: return int(item) except TypeError: return None elif item_type == 'float': try: return float(item) except TypeError: return None elif item_type in ('string', 'str'): if item: return str(item) else: return None elif item_type in ('boolean', 'bool'): if type(item) is bool: return item else: return str(item).lower() in ('yes', 'true') elif item_type == 'ms': return Timing.string_to_ms(item) elif item_type == 'secs': return Timing.string_to_secs(item) elif item_type == 'list_of_lists': return Util.list_of_lists(item)
def preprocess_settings(self, settings, base_priority=0): """Takes an unstructured list of slide_player settings and processed them so they can be displayed. Args: settings: A list of dictionary of slide_player settings for a slide. base_priority: An integer that will be added to slide's priority from the config settings. Returns: A python list with all the settings in the right places. This method does a bunch of things, like making sure all the needed values are there, and moving certain things to the first and last elements when there are multiple elements used on one slide. (For example, if one of the elements wants to clear the slide, it has to happen first. If there's a transition, it has to happen last after the slide is built, etc. The returned settings list can be safely called with the by display() with the preprocessed=True flag. """ # This is a stupid band-aid because when modes load their slide_player # settings are already processed. I don't know why though, but I don't # have time to track it down now. $50 to anyone who figures out why!!! # Settings can be a list of dicts or just a dict. (Preprocessing is what # turns a dict into a list, though I don't know how sometimes items are # getting the preprocessed entry in their dict but they're not a list??? # todo if not settings: settings = list() settings.append(dict()) else: settings = deepcopy(settings) if type(settings) is list and 'preprocessed' in settings[0]: return settings elif type(settings) is dict and 'preprocessed' in settings: return [settings] processed_settings = list() if type(settings) is dict: settings = [settings] last_settings = dict() first_settings = dict() first_settings['preprocessed'] = True first_settings['persist_slide'] = False first_settings['clear_slide'] = False first_settings['expire'] = 0 first_settings['slide_name'] = None for element in settings: # Create a slide name based on the event name if one isn't specified if 'slide_name' in element: first_settings['slide_name'] = element.pop('slide_name') # If the config doesn't specify whether this slide should be made # active when this event is called, set a default value of True if 'slide_priority' in element: first_settings['slide_priority'] = ( element.pop('slide_priority') + base_priority) if 'clear_slide' in element: first_settings['clear_slide'] = element.pop('clear_slide') if 'slide' in element: first_settings['slide_name'] = element.pop('slide') if 'persist_slide' in element: first_settings['persist_slide'] = element.pop('persist_slide') if 'display' in element: first_settings['display'] = element.pop('display') if 'transition' in element: last_settings['transition'] = element.pop('transition') if 'expire' in element: first_settings['expire'] = Timing.string_to_ms( element.pop('expire')) processed_settings.append(element) if 'slide_priority' not in first_settings: first_settings['slide_priority'] = base_priority # Now add back in the items that need to be in the first element processed_settings[0].update(first_settings) # And add the settings we need to the last entry processed_settings[-1].update(last_settings) return processed_settings
def _initialize(self): # convert names to objects if self.config["ball_switches"]: for i in range(len(self.config["ball_switches"])): self.config["ball_switches"][i] = self.machine.switches[self.config["ball_switches"][i]] if self.config["eject_coil"]: self.config["eject_coil"] = self.machine.coils[self.config["eject_coil"]] if self.config["eject_switch"]: self.config["eject_switch"] = self.machine.switches[self.config["eject_switch"]] if self.config["entrance_switch"]: self.config["entrance_switch"] = self.machine.switches[self.config["entrance_switch"]] if self.config["jam_switch"]: self.config["jam_switch"] = self.machine.switches[self.config["jam_switch"]] if self.config["confirm_eject_type"] == "switch" and (self.config["confirm_eject_target"]): self.config["confirm_eject_switch"] = self.machine.switches[self.config["confirm_eject_switch"]] if self.config["eject_targets"]: for i in range(len(self.config["eject_targets"])): self.config["eject_targets"][i] = self.machine.balldevices[self.config["eject_targets"][i]] # make sure the eject timeouts list matches the length of the eject targets if len(self.config["eject_timeouts"]) < len(self.config["eject_targets"]): self.config["eject_timeouts"] += [None] * ( len(self.config["eject_targets"]) - len(self.config["eject_timeouts"]) ) timeouts_list = self.config["eject_timeouts"] self.config["eject_timeouts"] = dict() for i in range(len(self.config["eject_targets"])): self.config["eject_timeouts"][self.config["eject_targets"][i]] = Timing.string_to_ms(timeouts_list[i]) # End code to create timeouts list ------------------------------------- # Register switch handlers with delays for entrance & exit counts for switch in self.config["ball_switches"]: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=self.config["entrance_count_delay"], callback=self.count_balls ) for switch in self.config["ball_switches"]: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=self.config["exit_count_delay"], callback=self.count_balls ) for switch in self.config["ball_switches"]: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=0, callback=self._invalidate ) for switch in self.config["ball_switches"]: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=0, callback=self._invalidate ) # Configure switch handlers for jam switch activity if self.config["jam_switch"]: self.machine.switch_controller.add_switch_handler( switch_name=self.config["jam_switch"].name, state=1, ms=0, callback=self._jam_switch_handler ) # todo do we also need to add inactive and make a smarter # handler? # Configure switch handlers for entrance switch activity if self.config["entrance_switch"]: self.machine.switch_controller.add_switch_handler( switch_name=self.config["entrance_switch"].name, state=1, ms=0, callback=self._entrance_switch_handler ) # todo do we also need to add inactive and make a smarter # handler? # Configure event handlers to watch for target device status changes for target in self.config["eject_targets"]: # Target device is requesting a ball self.machine.events.add_handler( "balldevice_" + target.name + "_ball_request", self.eject, target=target, get_ball=True ) # Target device is now able to receive a ball self.machine.events.add_handler("balldevice_" + target.name + "_ok_to_receive", self._do_eject) # Get an initial ball count self.count_balls(stealth=True)
def validate_config_item(spec, item='item not in config!@#'): try: if item.lower() == 'none': item = None except AttributeError: pass default = 'default required!@#' if '|' in spec: item_type, default = spec.split('|') if type(default) is str and default.lower() == 'none': default = None else: item_type = spec if item == 'item not in config!@#': if default == 'default required!@#': log.error( 'Required setting missing from config file. Run with ' 'verbose logging and look for the last ' 'ConfigProcessor entry above this line to see where ' 'the problem is.') sys.exit() else: item = default if item_type == 'list': return Util.string_to_list(item) if item_type == 'list_of_dicts': if type(item) is list: return item elif type(item) is dict: return [item] elif item_type == 'set': return set(Util.string_to_list(item)) elif item_type == 'dict': if type(item) is dict or type(item) is CaseInsensitiveDict: return item elif not default: return dict() else: log.error('Config error. "%s" is not a dictionary', item) sys.exit() elif item_type == 'int': try: return int(item) except TypeError: return None elif item_type == 'float': try: return float(item) except TypeError: return None elif item_type in ('string', 'str'): if item: return str(item) else: return None elif item_type in ('boolean', 'bool'): if type(item) is bool: return item else: return str(item).lower() in ('yes', 'true') elif item_type == 'ms': return Timing.string_to_ms(item) elif item_type == 'secs': return Timing.string_to_secs(item) elif item_type == 'list_of_lists': return Util.list_of_lists(item)
def _initialize(self): # convert names to objects # make sure the eject timeouts list matches the length of the eject targets if (len(self.config['eject_timeouts']) < len(self.config['eject_targets'])): self.config['eject_timeouts'] += [None] * ( len(self.config['eject_targets']) - len(self.config['eject_timeouts'])) timeouts_list = self.config['eject_timeouts'] self.config['eject_timeouts'] = dict() for i in range(len(self.config['eject_targets'])): self.config['eject_timeouts'][self.config['eject_targets'][i]] = ( Timing.string_to_ms(timeouts_list[i])) # End code to create timeouts list ------------------------------------- # Register switch handlers with delays for entrance & exit counts for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=self.config['entrance_count_delay'], callback=self.count_balls) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=self.config['exit_count_delay'], callback=self.count_balls) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=0, callback=self._invalidate) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=0, callback=self._invalidate) # Configure switch handlers for jam switch activity if self.config['jam_switch']: self.machine.switch_controller.add_switch_handler( switch_name=self.config['jam_switch'].name, state=1, ms=0, callback=self._jam_switch_handler) # todo do we also need to add inactive and make a smarter # handler? # Configure switch handlers for entrance switch activity if self.config['entrance_switch']: self.machine.switch_controller.add_switch_handler( switch_name=self.config['entrance_switch'].name, state=1, ms=0, callback=self._entrance_switch_handler) # todo do we also need to add inactive and make a smarter # handler? # handle hold_coil activation when a ball hits a switch for switch in self.config['hold_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=0, callback=self._enable_hold_coil) # Configure event handlers to watch for target device status changes for target in self.config['eject_targets']: # Target device is requesting a ball self.machine.events.add_handler('balldevice_' + target.name + '_ball_request', self.eject, target=target, get_ball=True) # Target device is now able to receive a ball self.machine.events.add_handler('balldevice_' + target.name + '_ok_to_receive', self._do_eject) # Get an initial ball count self.count_balls(stealth=True)
def __init__(self, machine, name, config, collection=None): self.log = logging.getLogger('Diverter.' + name) super(Diverter, self).__init__(machine, name, config, collection) self.delay = DelayManager() # Attributes self.active = False self.enabled = False self.platform = None # configure defaults: if 'type' not in self.config: self.config['type'] = 'pulse' # default to pulse to not fry coils if 'activation_time' not in self.config: self.config['activation_time'] = 0 if 'activation_switches' in self.config: self.config['activation_switches'] = Config.string_to_list( self.config['activation_switches']) else: self.config['activation_switches'] = list() if 'disable_switches' in self.config: self.config['disable_switches'] = Config.string_to_list( self.config['disable_switches']) else: self.config['disable_switches'] = list() if 'deactivation_switches' in self.config: self.config['deactivation_switches'] = Config.string_to_list( self.config['deactivation_switches']) else: self.config['deactivation_switches'] = list() if 'activation_coil' in self.config: self.config['activation_coil'] = ( self.machine.coils[self.config['activation_coil']]) if 'deactivation_coil' in self.config: self.config['deactivation_coil'] = ( self.machine.coils[self.config['deactivation_coil']]) else: self.config['deactivation_coil'] = None if 'targets_when_active' in self.config: self.config['targets_when_active'] = Config.string_to_list( self.config['targets_when_active']) else: self.config['targets_when_active'] = ['playfield'] if 'targets_when_inactive' in self.config: self.config['targets_when_inactive'] = Config.string_to_list( self.config['targets_when_inactive']) else: self.config['targets_when_inactive'] = ['playfield'] if 'feeder_devices' in self.config: self.config['feeder_devices'] = Config.string_to_list( self.config['feeder_devices']) else: self.config['feeder_devices'] = list() # Create a list of ball device objects when active and inactive. We need # this because ball eject attempts pass the target device as an object # rather than by name. self.config['active_objects'] = list() self.config['inactive_objects'] = list() for target_device in self.config['targets_when_active']: if target_device == 'playfield': self.config['active_objects'].append('playfield') else: self.config['active_objects'].append( self.machine.balldevices[target_device]) for target_device in self.config['targets_when_inactive']: if target_device == 'playfield': self.config['inactive_objects'].append('playfield') else: self.config['inactive_objects'].append( self.machine.balldevices[target_device]) # convert the activation_time to ms self.config['activation_time'] = Timing.string_to_ms( self.config['activation_time']) # register for events for event in self.config['enable_events']: self.machine.events.add_handler(event, self.enable) for event in self.config['disable_events']: self.machine.events.add_handler(event, self.disable) # register for feeder device eject events for feeder_device in self.config['feeder_devices']: self.machine.events.add_handler( 'balldevice_' + feeder_device + '_ball_eject_attempt', self._feeder_eject_attempt) self.machine.events.add_handler('init_phase_3', self._register_switches) self.platform = self.config['activation_coil'].platform
def _initialize(self): # convert names to objects if self.config['ball_switches']: for i in range(len(self.config['ball_switches'])): self.config['ball_switches'][i] = ( self.machine.switches[self.config['ball_switches'][i]]) if self.config['eject_coil']: self.config['eject_coil'] = ( self.machine.coils[self.config['eject_coil']]) if self.config['eject_switch']: self.config['eject_switch'] = ( self.machine.switches[self.config['eject_switch']]) if self.config['entrance_switch']: self.config['entrance_switch'] = ( self.machine.switches[self.config['entrance_switch']]) if self.config['jam_switch']: self.config['jam_switch'] = ( self.machine.switches[self.config['jam_switch']]) if self.config['confirm_eject_type'] == 'switch' and ( self.config['confirm_eject_target']): self.config['confirm_eject_switch'] = ( self.machine.switches[self.config['confirm_eject_switch']]) if self.config['eject_targets']: for i in range(len(self.config['eject_targets'])): self.config['eject_targets'][i] = ( self.machine.balldevices[self.config['eject_targets'][i]]) # make sure the eject timeouts list matches the length of the eject targets if (len(self.config['eject_timeouts']) < len( self.config['eject_targets'])): self.config['eject_timeouts'] += [None] * ( len(self.config['eject_targets']) - len(self.config['eject_timeouts'])) timeouts_list = self.config['eject_timeouts'] self.config['eject_timeouts'] = dict() for i in range(len(self.config['eject_targets'])): self.config['eject_timeouts'][self.config['eject_targets'][i]] = ( Timing.string_to_ms(timeouts_list[i])) # End code to create timeouts list ------------------------------------- # Register switch handlers with delays for entrance & exit counts for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=self.config['entrance_count_delay'], callback=self.count_balls) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=self.config['exit_count_delay'], callback=self.count_balls) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=1, ms=0, callback=self._invalidate) for switch in self.config['ball_switches']: self.machine.switch_controller.add_switch_handler( switch_name=switch.name, state=0, ms=0, callback=self._invalidate) # Configure switch handlers for jam switch activity if self.config['jam_switch']: self.machine.switch_controller.add_switch_handler( switch_name=self.config['jam_switch'].name, state=1, ms=0, callback=self._jam_switch_handler) # todo do we also need to add inactive and make a smarter # handler? # Configure switch handlers for entrance switch activity if self.config['entrance_switch']: self.machine.switch_controller.add_switch_handler( switch_name=self.config['entrance_switch'].name, state=1, ms=0, callback=self._entrance_switch_handler) # todo do we also need to add inactive and make a smarter # handler? # Configure event handlers to watch for target device status changes for target in self.config['eject_targets']: # Target device is requesting a ball self.machine.events.add_handler('balldevice_' + target.name + '_ball_request', self.eject, target=target, get_ball=True) # Target device is now able to receive a ball self.machine.events.add_handler( 'balldevice_' + target.name + '_ok_to_receive', self._do_eject) # Get an initial ball count self.count_balls(stealth=True)
def validate_item(self, item, validator, validation_failure_info): try: if item.lower() == 'none': item = None except AttributeError: pass if ':' in validator: validator = validator.split(':') # item could be str, list, or list of dicts item = Util.event_config_to_dict(item) return_dict = dict() for k, v in item.iteritems(): return_dict[self.validate_item( k, validator[0], validation_failure_info)] = (self.validate_item( v, validator[1], validation_failure_info)) item = return_dict elif '%' in validator: if type(item) is str: try: item = eval(validator.replace('%', "'" + item + "'")) except KeyError: self.validation_error(item, validation_failure_info) else: item = None elif validator == 'str': if item is not None: item = str(item) else: item = None elif validator == 'float': try: item = float(item) except (TypeError, ValueError): # TODO error pass elif validator == 'int': try: item = int(item) except (TypeError, ValueError): # TODO error pass elif validator in ('bool', 'boolean'): if type(item) is str: if item.lower() in ['false', 'f', 'no', 'disable', 'off']: item = False elif not item: item = False else: item = True elif validator == 'ms': item = Timing.string_to_ms(item) elif validator == 'secs': item = Timing.string_to_secs(item) elif validator == 'ticks': item = Timing.string_to_ticks(item) elif validator == 'ticks_int': item = int(Timing.string_to_ticks(item)) elif validator == 'list': item = Util.string_to_list(item) else: self.log.error("Invalid Validator '%s' in config spec %s:%s", validator, validation_failure_info[0][0], validation_failure_info[1]) sys.exit() return item