def __init__(self, machine: "MachineController", name: str) -> None: """Initialise spinner device.""" super().__init__(machine, name) self._active = False self._idle = True self._active_ms = None self.hits = None self.delay = DelayManager(machine) self.enabled = True # Default to enabled
def __init__(self, machine: MachineController, name: str) -> None: """Initialise counter.""" super().__init__(machine, name) self.debug_log("Creating Counter LogicBlock") self.delay = DelayManager(self.machine) self.ignore_hits = False self.hit_value = -1
def test_zero_ms_delay(self): self.called = False self.delay = DelayManager(self.machine.delayRegistry) self.delay.add(ms=0, name="first", callback=self.delay_zero_ms, start=self.machine.clock.get_time()) self.advance_time_and_run(10)
def __init__(self, machine: MachineController, name: str) -> None: """Initialise driver.""" self.hw_driver = None # type: DriverPlatformInterface super().__init__(machine, name) self.delay = DelayManager(self.machine.delayRegistry) self.time_last_changed = -1 self.time_when_done = -1 self.platform = None # type: DriverPlatform
def __init__(self, machine, name): """Initialise multiball.""" self.ball_locks = None self.source_playfield = None super().__init__(machine, name) self.delay = DelayManager(machine) self.balls_added_live = 0 self.balls_live_target = 0 self.shoot_again = False
def __init__(self, machine, name): """Initialise drop target.""" self.reset_coil = None self.knockdown_coil = None self.banks = None super().__init__(machine, name) self._in_ball_search = False self.complete = False self.delay = DelayManager(machine.delayRegistry)
def __init__(self, machine, name): """Initialise servo.""" self.hw_servo = None self.platform = None # type: ServoPlatform self._position = None self.speed_limit = None self.acceleration_limit = None self._ball_search_started = False self.delay = DelayManager(machine) super().__init__(machine, name)
def __init__(self, machine, name): """Initialise ball save.""" self.unlimited_saves = None self.source_playfield = None super().__init__(machine, name) self.delay = DelayManager(machine.delayRegistry) self.enabled = False self.timer_started = False self.saves_remaining = 0
def __init__(self, machine, name): """Initialize Combo Switch.""" super().__init__(machine, name) self.states = ['inactive', 'both', 'one'] self._state = 'inactive' self._switches_1_active = False self._switches_2_active = False self.delay_registry = DelayManagerRegistry(self.machine) self.delay = DelayManager(self.delay_registry)
def __init__(self, machine: "MachineController", config, name: str, path) -> None: """Initialise mode. Args: machine: the machine controller config: config dict for mode name: name of mode path: path of mode """ super().__init__() self.machine = machine # type: MachineController self.config = config # type: ignore self.name = name self.path = path self.priority = 0 self._active = False self._starting = False self._mode_start_wait_queue = None # type: QueuedEvent self.stop_methods = list() # type: List[Tuple[Callable[[Any], None], Any]] self.start_callback = None # type: Callable[[], None] self.stop_callbacks = [] # type: List[Callable[[], None]] self.event_handlers = set() # type: Set[EventHandlerKey] self.switch_handlers = list() # type: List[SwitchHandler] self.mode_stop_kwargs = dict() # type: Dict[str, Any] self.mode_devices = set() # type: Set[ModeDevice] self.start_event_kwargs = None # type: Dict[str, Any] self.stopping = False self.delay = DelayManager(self.machine) '''DelayManager instance for delays in this mode. Note that all delays scheduled here will be automatically canceled when the mode stops.''' self.player = None # type: Player '''Reference to the current player object.''' self.configure_logging('Mode.' + name, self.config['mode']['console_log'], self.config['mode']['file_log']) self.configure_mode_settings(config.get('mode', dict())) self.auto_stop_on_ball_end = self.config['mode']['stop_on_ball_end'] '''Controls whether this mode is stopped when the ball ends, regardless of its stop_events settings. ''' self.restart_on_next_ball = self.config['mode']['restart_on_next_ball'] '''Controls whether this mode will restart on the next ball. This only works if the mode was running when the ball ended. It's tracked per- player in the 'restart_modes_on_next_ball' player variable. ''' if self.config['mode']['game_mode'] and not self.config['mode']['stop_on_ball_end']: self.raise_config_error("All game modes need to stop at ball end. If you want to set stop_on_ball_end to " "False also set game_mode to False.", 1)
def __init__(self, machine: "MachineController", name: str) -> None: """Initialise autofire.""" self._enabled = False self._rule = None # type: HardwareRule super().__init__(machine, name) self.delay = DelayManager(self.machine) self._ball_search_in_progress = False self._timeout_watch_time = None self._timeout_max_hits = None self._timeout_disable_time = None self._timeout_hits = [] # type: List[float]
def test_event_in_delay(self): self.machine.events.add_handler('event1', self.event1_cb) self.machine.events.add_handler('event2', self.event2_cb) self.machine.events.add_handler('event3', self.event3_cb) self.correct = False self.delay = DelayManager(self.machine) self.machine.events.post("event1") self.advance_time_and_run(1) self.assertTrue(self.correct)
def __init__(self, machine, name): """Initialise blinkenlight.""" super().__init__(machine, name) self._colors = [] self.delay = DelayManager(machine) self._color_duration = None self._cycle_duration = None self.num_colors = 0 self._light_key = 'blinkenlight_{}'.format( self.name) # cache the key as string operations as expensive
def __init__(self, config, ball_device, machine): """Initialise ejector.""" for option in ["eject_coil", "eject_coil_enable_time"]: if option not in config and option in ball_device.config: config[option] = ball_device.config[option] super().__init__(config, ball_device, machine) self.delay = DelayManager(self.ball_device.machine) self.config = self.machine.config_validator.validate_config( "ball_device_ejector_enable", self.config)
def __init__(self, machine, name): """Initialise score reel.""" super().__init__(machine, name) self.delay = DelayManager(machine.delayRegistry) self.rollover_reel_advanced = False # True when a rollover pulse has been ordered self.value_switches = [] # This is a list with each element corresponding to a value on the # reel. An entry of None means there's no value switch there. An entry # of a reference to a switch object (todo or switch name?) means there # is a switch there. self.num_values = 0 # The number of values on this wheel. This starts with zero, so a # wheel with 10 values will have this value set to 9. (This actually # makes sense since most (all?) score reels also have a zero value.) self.physical_value = -999 # The physical confirmed value of this reel. This will always be the # value of whichever switch is active or -999. This differs from # `self.assumed_value` in that assumed value will make assumptions about # where the reel is as it pulses through values with no swithces, # whereas this physical value will always be -999 if there is no switch # telling it otherwise. # Note this value will be initialized via self.check_hw_switches() # below. self.hw_sync = False # Specifies whether this reel has verified it's positions via the # switches since it was last advanced.""" self.ready = True # Whether this reel is ready to advance. Typically used to make sure # it's not trying to re-fire a stuck position. self.assumed_value = -999 # The assumed value the machine thinks this reel is showing. A value # of -999 indicates that the value is unknown. self.next_pulse_time = 0 # The time when this reel next wants to be pulsed. The reel will set # this on its own (based on its own attribute of how fast pulses can # happen). If the ScoreReelController is ready to pulse this reel and # the value is in the past, it will do a pulse. A value of 0 means this # reel does not currently need to be pulsed. self.rollover_reel = None # A reference to the ScoreReel object of the next higher reel in the # group. This is used so the reel can notify its neighbor that it needs # to advance too when this reel rolls over. self._destination_index = 0
def __init__(self, machine, name): """Initialise drop target bank.""" super().__init__(machine, name) self.drop_targets = list() self.reset_coil = None self.reset_coils = set() self.complete = False self.down = 0 self.up = 0 self.delay = DelayManager(machine.delayRegistry) self._ignore_switch_hits = False
def __init__(self, machine: "MachineController", name: str) -> None: """Initialise drop target bank.""" super().__init__(machine, name) self.drop_targets = list() # type: List[DropTarget] self.reset_coil = None # type: Driver self.reset_coils = set() # type: Set[Driver] self.complete = False self.down = 0 self.up = 0 self.delay = DelayManager(machine.delayRegistry) self._ignore_switch_hits = False
def __init__(self, machine: "MachineController", name: str) -> None: """Initialise drop target.""" self.reset_coil = None # type: Driver self.knockdown_coil = None # type: Driver self.banks = None # type: Set[DropTargetBank] super().__init__(machine, name) self._in_ball_search = False self.complete = False self.delay = DelayManager(machine.delayRegistry) self._ignore_switch_hits = False
def __init__(self, ball_device, config): """Initialise entrance switch counter.""" for option in ["entrance_switch", "entrance_switch_ignore_window_ms", "entrance_switch_full_timeout", "ball_capacity"]: if option not in config and option in ball_device.config: config[option] = ball_device.config[option] super().__init__(ball_device, config) self._settle_delay = DelayManager(self.machine) self.config = self.machine.config_validator.validate_config("ball_device_counter_entrance_switches", self.config) self.recycle_secs = self.config['entrance_switch_ignore_window_ms'] / 1000.0 self.recycle_clear_time = {} for switch in self.config['entrance_switch']: # Configure switch handlers for entrance switch activity self.machine.switch_controller.add_switch_handler_obj( switch=switch, state=1, ms=0, callback=self._entrance_switch_handler, callback_kwargs={"switch_name": switch.name}) self.machine.switch_controller.add_switch_handler_obj( switch=switch, state=0, ms=0, callback=self._entrance_switch_released_handler, callback_kwargs={"switch_name": switch.name}) if self.config['entrance_switch_full_timeout'] and self.config['ball_capacity']: if len(self.config['entrance_switch']) > 1: raise AssertionError("entrance_switch_full_timeout not supported with multiple entrance switches.") self.machine.switch_controller.add_switch_handler_obj( switch=self.config['entrance_switch'][0], state=1, ms=self.config['entrance_switch_full_timeout'], callback=self._entrance_switch_full_handler) # Handle initial ball count with entrance_switch. If there is a ball on the entrance_switch at boot # assume that we are at max capacity. if (self.config['ball_capacity'] and self.config['entrance_switch_full_timeout'] and self.machine.switch_controller.is_active(self.config['entrance_switch'][0], ms=self.config['entrance_switch_full_timeout'])): self._last_count = self.config['ball_capacity'] else: self._last_count = 0 self._count_stable.set() # TODO validate that we are not used with mechanical eject if not self.config['ball_capacity']: self.ball_device.raise_config_error("Need ball capacity if there are no switches.", 2) elif self.ball_device.config.get('ball_switches'): self.ball_device.raise_config_error("Cannot use capacity and ball switches.", 3)
class EnableCoilEjector(PulseCoilEjector): """Enable a coil to eject one ball.""" __slots__ = ["delay"] def __init__(self, config, ball_device, machine): """Initialise ejector.""" super().__init__(config, ball_device, machine) self.delay = DelayManager(self.ball_device.machine.delayRegistry) def _validate_config(self): # overwrite validation from pulse_coil_ejector pass @asyncio.coroutine def eject_one_ball(self, is_jammed, eject_try): """Enable eject coil.""" del is_jammed del eject_try # If multiple eject_coil_enable_time values, they correspond to the # of balls if self.ball_device.balls <= len( self.ball_device.config['eject_coil_enable_time']): eject_time = self.ball_device.config['eject_coil_enable_time'][ self.ball_device.balls - 1] else: eject_time = self.ball_device.config['eject_coil_enable_time'][-1] # default pulse self.ball_device.debug_log( "Enabling eject coil for %sms, Current balls: %s.", eject_time, self.ball_device.balls) self.ball_device.config['eject_coil'].enable() self.delay.reset(name="disable", callback=self._disable_coil, ms=eject_time) def _disable_coil(self): """Disable the coil.""" self.ball_device.config['eject_coil'].disable() def _fire_coil_for_search(self, full_power): if full_power and self.ball_device.config['eject_coil_jam_pulse']: self.ball_device.config['eject_coil'].pulse() else: self.ball_device.config['eject_coil'].enable() self.delay.reset( name="disable", callback=self._disable_coil, ms=self.ball_device.config['eject_coil_enable_time'][0]) return True
def __init__(self, machine, name): """Initialise diverter.""" super().__init__(machine, name) self.delay = DelayManager(machine) # Attributes self.active = False self.enabled = False self.diverting_ejects_count = 0 self.eject_state = False self.eject_attempt_queue = deque()
def __init__(self, machine, name): """Initialise stepper.""" self.hw_stepper = None # type: Optional[StepperPlatformInterface] self.platform = None # type: Optional[Stepper] self._target_position = 0 # in user units self._current_position = 0 # in user units self._ball_search_started = False self._ball_search_old_target = 0 self._is_homed = False self._is_moving = asyncio.Event(loop=machine.clock.loop) self._move_task = None # type: Optional[asyncio.Task] self.delay = DelayManager(machine) super().__init__(machine, name)
def __init__(self, machine: "MachineController", name: str) -> None: """Initialise ball save.""" self.unlimited_saves = None # type: bool self.source_playfield = None # type: Playfield super().__init__(machine, name) self.delay = DelayManager(machine.delayRegistry) self.enabled = False self.timer_started = False self.saves_remaining = 0 self.early_saved = 0 self.state = 'disabled' self._scheduled_balls = 0
def __init__(self, machine, mode, name, config): """Initialise mode timer.""" self.machine = machine self.mode = mode self.name = name self.config = config self.running = False self.start_value = self.config['start_value'].evaluate([]) self.restart_on_complete = self.config['restart_on_complete'] self._ticks = 0 self.tick_var = '{}_{}_tick'.format(self.mode.name, self.name) try: self.end_value = self.config['end_value'].evaluate([]) except AttributeError: self.end_value = None self.ticks_remaining = 0 self.max_value = self.config['max_value'] self.direction = self.config['direction'].lower() self.tick_secs = self.config['tick_interval'] / 1000.0 self.timer = None self.event_keys = set() self.delay = DelayManager(self.machine.delayRegistry) if self.config['debug']: self.configure_logging('Timer.' + name, 'full', 'full') else: self.configure_logging('Timer.' + name, self.config['console_log'], self.config['file_log']) if self.direction == 'down' and not self.end_value: self.end_value = 0 # need it to be 0 not None self.ticks = self.start_value self.debug_log("----------- Initial Values -----------") self.debug_log("running: %s", self.running) self.debug_log("start_value: %s", self.start_value) self.debug_log("restart_on_complete: %s", self.restart_on_complete) self.debug_log("_ticks: %s", self.ticks) self.debug_log("end_value: %s", self.end_value) self.debug_log("ticks_remaining: %s", self.ticks_remaining) self.debug_log("max_value: %s", self.max_value) self.debug_log("direction: %s", self.direction) self.debug_log("tick_secs: %s", self.tick_secs) self.debug_log("--------------------------------------") if self.config['control_events']: self._setup_control_events(self.config['control_events'])
def __init__(self, machine, name): """Initialise light.""" self.hw_drivers = {} self.platforms = set() # type: Set[LightsPlatform] super().__init__(machine, name) self.machine.light_controller.initialise_light_subsystem() self.delay = DelayManager(self.machine.delayRegistry) self.default_fade_ms = None self._color_correction_profile = None self.stack = list() """A list of dicts which represents different commands that have come
def __init__(self, machine, config, name: str, path) -> None: """Initialise mode. Args: machine(mpf.core.machine.MachineController): the machine controller config: config dict for mode name: name of mode path: path of mode Returns: """ super().__init__() self.machine = machine self.config = config # type: ignore self.name = name.lower() self.path = path self.priority = 0 self._active = False self._mode_start_wait_queue = None # type: QueuedEvent self.stop_methods = list() # type: List[Tuple[Callable[[Any], None], Any]] self.start_callback = None # type: Callable[[], None] self.stop_callbacks = [] # type: List[Callable[[], None]] self.event_handlers = set() # type: Set[EventHandlerKey] self.switch_handlers = list() # type: List[SwitchHandler] self.mode_stop_kwargs = dict() # type: Dict[str, Any] self.mode_devices = set() # type: Set[ModeDevice] self.start_event_kwargs = None # type: Dict[str, Any] self.stopping = False self.delay = DelayManager(self.machine.delayRegistry) '''DelayManager instance for delays in this mode. Note that all delays scheduled here will be automatically canceled when the mode stops.''' self.player = None # type: Player '''Reference to the current player object.''' self.configure_logging('Mode.' + name, self.config['mode']['console_log'], self.config['mode']['file_log']) self.configure_mode_settings(config.get('mode', dict())) self.auto_stop_on_ball_end = self.config['mode']['stop_on_ball_end'] '''Controls whether this mode is stopped when the ball ends, regardless of its stop_events settings. ''' self.restart_on_next_ball = self.config['mode']['restart_on_next_ball'] '''Controls whether this mode will restart on the next ball. This only
class EventPlayer(FlatConfigPlayer): """Posts events based on config.""" config_file_section = 'event_player' show_section = 'events' __slots__ = ["delay"] def __init__(self, machine): """Initialise EventPlayer.""" super().__init__(machine) self.delay = DelayManager(self.machine.delayRegistry) def play(self, settings, context, calling_context, priority=0, **kwargs): """Post (delayed) events.""" for event, s in settings.items(): s = deepcopy(s) event_dict = self.machine.placeholder_manager.parse_conditional_template( event) if event_dict['condition'] and not event_dict[ 'condition'].evaluate(kwargs): continue if event_dict['number']: delay = Util.string_to_ms(event_dict['number']) self.delay.add(callback=self._post_event, ms=delay, event=event_dict['name'], s=s) else: self._post_event(event_dict['name'], s) def _post_event(self, event, s): event_name_placeholder = TextTemplate( self.machine, event.replace("(", "{").replace(")", "}")) self.machine.events.post(event_name_placeholder.evaluate({}), **s) def get_list_config(self, value): """Parse list.""" result = {} for event in value: result[event] = {} return result def get_express_config(self, value): """Parse short config.""" return self.get_list_config(Util.string_to_list(value))
def __init__(self, machine): """Initialise ball controller.""" self.machine = machine self.log = logging.getLogger("BallController") self.log.debug("Loading the BallController") self.delay = DelayManager(self.machine.delayRegistry) self.num_balls_known = -999 # register for events self.machine.events.add_handler('request_to_start_game', self.request_to_start_game) self.machine.events.add_handler('machine_reset_phase_2', self._initialize) self.machine.events.add_handler('init_phase_2', self._init2)
def __init__(self, machine: "MachineController", name: str) -> None: """Initialise ball save.""" self.ball_locks = None self.unlimited_saves = None # type: Optional[bool] self.source_playfield = None # type: Optional[Playfield] super().__init__(machine, name) self.delay = DelayManager(machine) self.enabled = False self.timer_started = False self.saves_remaining = 0 self.early_saved = 0 self.state = 'disabled' self._scheduled_balls = 0 self.active_time = 0
def __init__(self, machine, name): """Initialise ball device.""" super().__init__(machine, name) self.delay = DelayManager(machine) self.available_balls = 0 """Number of balls that are available to be ejected. This differs from `balls` since it's possible that this device could have balls that are being used for some other eject, and thus not available.""" self._target_on_unexpected_ball = None # Device will eject to this target when it captures an unexpected ball self._source_devices = list() # Ball devices that have this device listed among their eject targets self._ball_requests = deque() # deque of tuples that holds requests from target devices for balls # that this device could fulfil # each tuple is (target device, boolean player_controlled flag) self.ejector = None # type: BallDeviceEjector self.ball_count_handler = None # type: BallCountHandler self.incoming_balls_handler = None # type: IncomingBallsHandler self.outgoing_balls_handler = None # type: OutgoingBallsHandler # mirrored from ball_count_handler to make it obserable by the monitor self.counted_balls = 0 self._state = "idle"