def test_enable_and_disable(self): coil = self.machine.coils['coil_1'] coil.hw_driver.enable = MagicMock() coil.hw_driver.pulse = MagicMock() coil.hw_driver.disable = MagicMock() self.machine.events.post('event4') self.advance_time_and_run() coil.hw_driver.enable.assert_called_with( PulseSettings(power=1.0, duration=10), HoldSettings(power=1.0)) assert not coil.hw_driver.pulse.called self.machine.events.post('event5') self.advance_time_and_run() coil.hw_driver.disable.assert_called_with() # same again but use on and off instead of enable and disable coil.hw_driver.enable = MagicMock() coil.hw_driver.pulse = MagicMock() coil.hw_driver.disable = MagicMock() self.machine.events.post('event10') self.advance_time_and_run() coil.hw_driver.enable.assert_called_with( PulseSettings(power=1.0, duration=10), HoldSettings(power=1.0)) assert not coil.hw_driver.pulse.called self.machine.events.post('event11') self.advance_time_and_run() coil.hw_driver.disable.assert_called_with()
def test_single(self): self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock( ) self.machine.flippers["f_test_single"].enable() self.assertEqual( 1, len(self.machine.default_platform. set_pulse_on_hit_and_enable_and_release_rule. _mock_call_args_list)) self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings( hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils["c_flipper_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=0.125), recycle=False)) self.machine.default_platform.clear_hw_rule = MagicMock() self.machine.flippers["f_test_single"].disable() self.assertEqual(1, self.machine.default_platform.clear_hw_rule.called) self.machine.default_platform.clear_hw_rule.assert_called_once_with( SwitchSettings( hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils["c_flipper_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=0.125), recycle=False))
def test_pulse(self): coil = self.machine.coils['coil_1'] coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() # coil without allow_enable coil2 = self.machine.coils['coil_2'] coil2.hw_driver.pulse = MagicMock() coil2.hw_driver.enable = MagicMock() self.machine.events.post('event2') self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with(PulseSettings(power=1.0, duration=10)) assert not coil.hw_driver.enable.called coil2.hw_driver.pulse.assert_called_with(PulseSettings(power=0.5, duration=10)) assert not coil2.hw_driver.enable.called # post same event again coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() coil2.hw_driver.pulse = MagicMock() coil2.hw_driver.enable = MagicMock() self.machine.events.post('event2') self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with(PulseSettings(power=1.0, duration=10)) assert not coil.hw_driver.enable.called coil2.hw_driver.pulse.assert_called_with(PulseSettings(power=0.5, duration=10)) assert not coil2.hw_driver.enable.called
def test_hw_rule_pulse_inverted_autofire(self): self.machine.default_platform.set_pulse_on_hit_rule = MagicMock() self.machine.autofires["ac_test_inverted2"].enable() self.machine.default_platform.set_pulse_on_hit_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_test"].hw_switch, invert=True, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_test2"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=23), hold_settings=None, recycle=True)) self.machine.default_platform.clear_hw_rule = MagicMock() self.machine.autofires["ac_test_inverted2"].disable() self.machine.default_platform.clear_hw_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_test"].hw_switch, invert=True, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_test2"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=23), hold_settings=None, recycle=True))
def test_flipper_with_settings(self): flipper = self.machine.flippers.f_test_flippers_with_settings self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock( ) flipper.enable() self.assertEqual( 1, len(self.machine.default_platform. set_pulse_on_hit_and_enable_and_release_rule. _mock_call_args_list)) self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches.s_flipper.hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils.c_flipper_main.hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=0.125), recycle=False)) self.machine.default_platform.clear_hw_rule = MagicMock() flipper.disable() self.assertEqual(1, self.machine.default_platform.clear_hw_rule.called) self.machine.default_platform.clear_hw_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches.s_flipper.hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils.c_flipper_main.hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=0.125), recycle=False)) self.machine.settings.set_setting_value("flipper_power", 0.8) self.advance_time_and_run() self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock( ) flipper.enable() self.assertEqual( 1, len(self.machine.default_platform. set_pulse_on_hit_and_enable_and_release_rule. _mock_call_args_list)) self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches.s_flipper.hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils.c_flipper_main.hw_driver, pulse_settings=PulseSettings(power=1.0, duration=8), hold_settings=HoldSettings(power=0.125), recycle=False)) self.assertEqual(8, flipper._get_pulse_ms())
def test_ac_switch_and_pulse(self): # test diag led flashing. otherwise snux is not running c_diag_led_driver = self.machine.coils.c_diag_led_driver c_diag_led_driver.pulse = MagicMock() self.advance_time_and_run(1) c_diag_led_driver.pulse.assert_called_with(250) # test if a and c side relays were properly loaded self.assertEqual(2, len(self._get_snux_platform().a_drivers)) self.assertEqual(2, len(self._get_snux_platform().c_drivers)) c_side_a1 = self._get_a_driver(self.machine.coils.c_side_a1) c_side_a2 = self._get_a_driver(self.machine.coils.c_side_a2) c_side_c1 = self._get_c_driver(self.machine.coils.c_side_c1) c_side_c2 = self._get_c_driver(self.machine.coils.c_side_c2) self.assertTrue(c_side_a1) self.assertTrue(c_side_a2) self.assertTrue(c_side_c1) self.assertTrue(c_side_c2) c_ac_relay = self.machine.coils.c_ac_relay c_ac_relay.enable = MagicMock() c_ac_relay.disable = MagicMock() c_side_a1.pulse = MagicMock() c_side_a2.enable = MagicMock() c_side_a2.disable = MagicMock() c_side_c1.pulse = MagicMock() c_side_c2.enable = MagicMock() c_side_c2.disable = MagicMock() # a side should be triggered first. c side should wait self.machine.coils.c_side_a1.pulse(50) self.machine.coils.c_side_c1.pulse(50) self.advance_time_and_run(0.001) c_side_a1.pulse.assert_called_with( PulseSettings(power=1.0, duration=50)) c_side_a1.pulse = MagicMock() assert not c_side_c1.pulse.called assert not c_ac_relay.enable.called # after 50ms + 75ms transition c side should get triggered self.advance_time_and_run(0.075) c_ac_relay.enable.assert_called_with() c_ac_relay.enable = MagicMock() assert not c_side_a1.pulse.called assert not c_side_c1.pulse.called # after the relay switches. pulse the other coil self.advance_time_and_run(0.075) assert not c_side_a1.pulse.called c_side_c1.pulse.assert_called_with( PulseSettings(power=1.0, duration=50)) # it should switch back to a side when idle self.advance_time_and_run(0.052) c_ac_relay.disable.assert_called_with() c_ac_relay.disable = MagicMock()
def test_express_config(self): # coil with allow_enable set coil = self.machine.coils['coil_1'] coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() self.machine.events.post('event1') self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=10)) assert not coil.hw_driver.enable.called # coil without allow_enable coil = self.machine.coils['coil_2'] coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() self.machine.events.post('event6') self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=10)) assert not coil.hw_driver.enable.called coil = self.machine.coils['coil_3'] coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() coil.hw_driver.disable = MagicMock() self.post_event("event7") self.advance_time_and_run() coil.hw_driver.enable.assert_called_with( PulseSettings(power=1.0, duration=10), HoldSettings(power=0.5)) assert not coil.hw_driver.disable.called assert not coil.hw_driver.pulse.called coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() coil.hw_driver.disable = MagicMock() self.post_event("event8") self.advance_time_and_run() coil.hw_driver.disable.assert_called_with() assert not coil.hw_driver.enable.called assert not coil.hw_driver.pulse.called coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() coil.hw_driver.disable = MagicMock() self.post_event("event9") self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=30)) assert not coil.hw_driver.disable.called assert not coil.hw_driver.enable.called
def _pulse_now(self, pulse_ms: int, pulse_power: float) -> None: """Pulse this driver now.""" if 0 < pulse_ms <= self.platform.features['max_pulse']: self.info_log("Pulsing Driver for %sms (%s pulse_power)", pulse_ms, pulse_power) self.hw_driver.pulse(PulseSettings(power=pulse_power, duration=pulse_ms)) else: self.info_log("Enabling Driver for %sms (%s pulse_power)", pulse_ms, pulse_power) self.delay.reset(name='timed_disable', ms=pulse_ms, callback=self.disable) self.hw_driver.enable(PulseSettings(power=pulse_power, duration=0), HoldSettings(power=pulse_power)) # inform bcp clients self.machine.bcp.interface.send_driver_event(action="pulse", name=self.name, number=self.config['number'], pulse_ms=pulse_ms, pulse_power=pulse_power)
def configure_driver(self, config: DriverConfig, number: str, platform_settings: dict): """Configure a driver. Args: config: Config dict. """ if not self.opp_connection: self.raise_config_error("A request was made to configure an OPP solenoid, " "but no OPP connection is available", 4) number = self._get_dict_index(number) if number not in self.solDict: self.raise_config_error("A request was made to configure an OPP solenoid " "with number {} which doesn't exist".format(number), 5) # Use new update individual solenoid command opp_sol = self.solDict[number] opp_sol.config = config opp_sol.platform_settings = platform_settings self.log.debug("Configure driver %s", number) default_pulse = PulseSettings(config.default_pulse_power, config.default_pulse_ms) default_hold = HoldSettings(config.default_hold_power) opp_sol.reconfigure_driver(default_pulse, default_hold) # Removing the default input is not necessary since the # CFG_SOL_USE_SWITCH is not being set return opp_sol
def remove_switch_rule(self): """Remove switch rule.""" self.switch_rule = None self.reconfigure_driver( PulseSettings(duration=self.config.default_pulse_ms if self.config.default_pulse_ms is not None else 10, power=self.config.default_pulse_power), HoldSettings(power=self.config.default_hold_power), True)
def _get_configured_driver_no_hold(driver: DriverRuleSettings, pulse_setting: PulseRuleSettings) -> DriverSettings: """Return configured driver without hold for rule.""" pulse_duration = driver.driver.get_and_verify_pulse_ms(pulse_setting.duration if pulse_setting else None) pulse_power = driver.driver.get_and_verify_pulse_power(pulse_setting.power if pulse_setting else None) return DriverSettings( hw_driver=driver.driver.hw_driver, pulse_settings=PulseSettings(duration=pulse_duration, power=pulse_power), hold_settings=None, recycle=driver.recycle)
def test_hold_with_eos(self): self.machine.default_platform.set_pulse_on_hit_and_release_and_disable_rule = MagicMock() self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock() self.machine.flippers["f_test_hold_eos"].enable() self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_hold"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=1.0), recycle=False) ) self.machine.default_platform.set_pulse_on_hit_and_release_and_disable_rule.assert_called_with( SwitchSettings(hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), SwitchSettings(hw_switch=self.machine.switches["s_flipper_eos"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=None, recycle=False), RepulseSettings(enable_repulse=False) ) self.machine.default_platform.clear_hw_rule = MagicMock() self.machine.flippers["f_test_hold_eos"].disable() self.machine.default_platform.clear_hw_rule.assert_has_calls([ call( SwitchSettings(hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=None, recycle=False) ), call( SwitchSettings(hw_switch=self.machine.switches["s_flipper_eos"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=None, recycle=False) ), call( SwitchSettings(hw_switch=self.machine.switches["s_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_hold"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=1.0), recycle=False) ), ], any_order=True)
def test_pulse_with_attributes(self): coil = self.machine.coils['coil_1'] coil.hw_driver.pulse = MagicMock() coil.hw_driver.enable = MagicMock() self.machine.events.post('event3') self.advance_time_and_run() coil.hw_driver.pulse.assert_called_with(PulseSettings(power=1.0, duration=49)) assert not coil.hw_driver.enable.called
def test_ac_switch_and_enable(self): c_side_a2 = self._get_a_driver(self.machine.coils.c_side_a2) c_side_c2 = self._get_c_driver(self.machine.coils.c_side_c2) c_side_a2.enable = MagicMock() c_side_a2.disable = MagicMock() c_side_c2.enable = MagicMock() c_side_c2.disable = MagicMock() c_ac_relay = self.machine.coils.c_ac_relay c_ac_relay.enable = MagicMock() c_ac_relay.disable = MagicMock() self.advance_time_and_run(0.10) # test enable on c side self.machine.coils.c_side_c2.enable() self.machine_run() c_ac_relay.enable.assert_called_with() c_ac_relay.enable = MagicMock() assert not c_side_c2.enable.called self.advance_time_and_run(0.075) c_side_c2.enable.assert_called_with( PulseSettings(power=1.0, duration=10), HoldSettings(power=0.5)) # a side has preference. it should transition self.machine.coils.c_side_a2.enable() self.machine_run() c_side_c2.disable.assert_called_with() c_ac_relay.disable.assert_called_with() c_ac_relay.disable = MagicMock() assert not c_side_a2.enable.called # it should enable a side coils now self.advance_time_and_run(0.075) c_side_a2.enable.assert_called_with( PulseSettings(power=1.0, duration=10), HoldSettings(power=0.5)) # disable driver on a side. self.machine.coils.c_side_a2.disable() self.advance_time_and_run(0.2)
def enable(self): """Enable digital output.""" if self.type == "driver": self.hw_driver.enable(PulseSettings(power=1.0, duration=0), HoldSettings(power=1.0)) elif self.type == "light": self.hw_driver.set_fade(1.0, -1, 1.0, -1) self.platform.light_sync() self.delay.remove(name='timed_disable') else: raise AssertionError(INVALID_TYPE_ERROR.format(self.type))
def enable(self): """Enable digital output.""" if self.type == "driver": self.hw_driver.enable(PulseSettings(power=1.0, duration=0), HoldSettings(power=1.0)) elif self.type == "light": self.hw_driver.set_fade(partial(self._get_state, state=True)) self.platform.light_sync() self.delay.remove(name='timed_disable') else: raise AssertionError("Invalid type {}".format(self.type))
def enable(self, **kwargs): """Enable digital output.""" del kwargs if self.type == "driver": self.hw_driver.enable(PulseSettings(power=1.0, duration=0), HoldSettings(power=1.0)) elif self.type == "light": self.hw_driver.set_fade(partial(self._get_state, state=True)) self.platform.light_sync() else: raise AssertionError("Invalid type {}".format(self.type))
def _get_configured_driver_with_optional_hold(driver: DriverRuleSettings, pulse_setting: PulseRuleSettings, hold_settings: HoldRuleSettings) -> DriverSettings: """Return configured driver for rule which might have hold.""" pulse_duration = driver.driver.get_and_verify_pulse_ms(pulse_setting.duration if pulse_setting else None) pulse_power = driver.driver.get_and_verify_pulse_power(pulse_setting.power if pulse_setting else None) hold_power = driver.driver.get_and_verify_hold_power(hold_settings.power if hold_settings else None) return DriverSettings( hw_driver=driver.driver.hw_driver, pulse_settings=PulseSettings(duration=pulse_duration, power=pulse_power), hold_settings=HoldSettings(power=hold_power), recycle=driver.recycle)
def pulse(self, pulse_ms): """Pulse digital output.""" if self.type == "driver": self.hw_driver.pulse(PulseSettings(power=1.0, duration=pulse_ms)) elif self.type == "light": self.hw_driver.set_fade(1.0, -1, 1.0, -1) self.platform.light_sync() self.delay.reset(name='timed_disable', ms=pulse_ms, callback=self.disable) else: raise AssertionError(INVALID_TYPE_ERROR.format(self.type))
def pulse(self, pulse_ms): """Pulse digital output.""" if self.type == "driver": self.hw_driver.pulse(PulseSettings(power=1.0, duration=pulse_ms)) elif self.type == "light": self.hw_driver.set_fade(partial(self._get_state, state=True)) self.platform.light_sync() self.delay.reset(name='timed_disable', ms=pulse_ms, callback=self.disable) else: raise AssertionError("Invalid type {}".format(self.type))
def enable(self, pulse_ms: int = None, pulse_power: float = None, hold_power: float = None): """Enable a driver by holding it 'on'. Args: ---- pulse_ms: The number of milliseconds the driver should be enabled for. If no value is provided, the driver will be enabled for the value specified in the config dictionary. pulse_power: The pulse power. A float between 0.0 and 1.0. hold_power: The pulse power. A float between 0.0 and 1.0. If this driver is configured with a holdpatter, then this method will use that holdpatter to pwm pulse the driver. If not, then this method will just enable the driver. As a safety precaution, if you want to enable() this driver without pwm, then you have to add the following option to this driver in your machine configuration files: allow_enable: True """ assert self.hw_driver is not None pulse_ms = self.get_and_verify_pulse_ms(pulse_ms) pulse_power = self.get_and_verify_pulse_power(pulse_power) hold_power = self.get_and_verify_hold_power(hold_power) if hold_power == 0.0: raise DriverLimitsError("Cannot enable driver with hold_power 0.0") self.info_log( "Enabling Driver with power %s (pulse_ms %sms and pulse_power %s)", hold_power, pulse_ms, pulse_power) self.hw_driver.enable( PulseSettings(power=pulse_power, duration=pulse_ms), HoldSettings(power=hold_power)) if self.config['max_hold_duration']: self.delay.add_if_doesnt_exist( self.config['max_hold_duration'] * 1000, self._enable_limit_reached, "enable_limit_reached") # inform bcp clients self.machine.bcp.interface.send_driver_event( action="enable", name=self.name, number=self.config['number'], pulse_ms=pulse_ms, pulse_power=pulse_power, hold_power=hold_power)
def testBasicFunctions(self): # Make sure hardware devices have been configured for tests self.assertIn('coil_01', self.machine.coils) self.assertIn('coil_02', self.machine.coils) # Setup platform function mock to test coil self.machine.coils.coil_01.hw_driver.disable = MagicMock() self.machine.coils.coil_01.hw_driver.enable = MagicMock() self.machine.coils.coil_01.hw_driver.pulse = MagicMock() self.machine.coils.coil_01.enable() self.machine.coils.coil_01.hw_driver.enable.assert_called_with( PulseSettings(power=1.0, duration=30), HoldSettings(power=1.0)) self.machine.coils.coil_01.pulse(100) self.machine.coils.coil_01.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=100)) self.machine.coils.coil_01.disable() self.machine.coils.coil_01.hw_driver.disable.assert_called_with() self.machine.coils.coil_03.hw_driver.disable = MagicMock() self.machine.coils.coil_03.hw_driver.enable = MagicMock() self.machine.coils.coil_03.hw_driver.pulse = MagicMock() # test default pulse_ms self.machine.config['mpf']['default_pulse_ms'] = 23 self.machine.coils.coil_03.pulse() self.machine.coils.coil_03.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=23)) # test power self.machine.config['mpf']['default_pulse_ms'] = 40 self.machine.coils.coil_03.pulse(pulse_power=1.0) self.machine.coils.coil_03.hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=40)) self.machine.coils.coil_03.pulse(pulse_power=0.5) self.machine.coils.coil_03.hw_driver.pulse.assert_called_with( PulseSettings(power=0.5, duration=40)) self.machine.coils.coil_01.enable(pulse_power=0.7, hold_power=0.3) self.machine.coils.coil_01.hw_driver.enable.assert_called_with( PulseSettings(power=0.7, duration=30), HoldSettings(power=0.3)) # test long pulse with delay self.machine.coils.coil_03.hw_driver.pulse = MagicMock() self.machine.coils.coil_03.hw_driver.enable = MagicMock() self.machine.coils.coil_03.hw_driver.disable = MagicMock() self.machine.coils.coil_03.pulse(pulse_ms=500) self.machine.coils.coil_03.hw_driver.enable.assert_called_with( PulseSettings(power=1.0, duration=0), HoldSettings(power=1.0)) self.machine.coils.coil_03.hw_driver.pulse.assert_not_called() self.advance_time_and_run(.5) self.machine.coils.coil_03.hw_driver.disable.assert_called_with()
def _get_configured_driver_with_hold(driver: DriverRuleSettings, pulse_setting: PulseRuleSettings, hold_settings: HoldRuleSettings) -> DriverSettings: """Return configured driver with hold > 0 for rule.""" pulse_duration = driver.driver.get_and_verify_pulse_ms(pulse_setting.duration if pulse_setting else None) pulse_power = driver.driver.get_and_verify_pulse_power(pulse_setting.power if pulse_setting else None) hold_power = driver.driver.get_and_verify_hold_power(hold_settings.power if hold_settings else None) if hold_power == 0.0: raise AssertionError("Cannot enable driver with hold_power 0.0") return DriverSettings( hw_driver=driver.driver.hw_driver, pulse_settings=PulseSettings(duration=pulse_duration, power=pulse_power), hold_settings=HoldSettings(power=hold_power), recycle=driver.recycle)
def enable(self, pulse_ms: int = None, pulse_power: float = None, hold_power: float = None, **kwargs): """Enable a driver by holding it 'on'. Args: pulse_ms: The number of milliseconds the driver should be enabled for. If no value is provided, the driver will be enabled for the value specified in the config dictionary. pulse_power: The pulse power. A float between 0.0 and 1.0. hold_power: The pulse power. A float between 0.0 and 1.0. If this driver is configured with a holdpatter, then this method will use that holdpatter to pwm pulse the driver. If not, then this method will just enable the driver. As a safety precaution, if you want to enable() this driver without pwm, then you have to add the following option to this driver in your machine configuration files: allow_enable: True """ del kwargs pulse_ms = self.get_and_verify_pulse_ms(pulse_ms) pulse_power = self.get_and_verify_pulse_power(pulse_power) hold_power = self.get_and_verify_hold_power(hold_power) if hold_power == 0.0: raise AssertionError("Cannot enable driver with hold_power 0.0") self.time_when_done = -1 self.time_last_changed = self.machine.clock.get_time() self.debug_log("Enabling Driver") self.hw_driver.enable( PulseSettings(power=pulse_power, duration=pulse_ms), HoldSettings(power=hold_power)) # inform bcp clients self.machine.bcp.interface.send_driver_event( action="enable", name=self.name, number=self.config['number'], pulse_ms=pulse_ms, pulse_power=pulse_power, hold_power=hold_power)
def test_kickback_with_ball_save(self): self.machine.default_platform.set_pulse_on_hit_rule = MagicMock() self.mock_event("kickback_kickback_test_fired") self.assertFalse(self.machine.ball_saves["kickback_save"].enabled) # kickback is not enabled. nothing should happen self.hit_and_release_switch("s_kickback") self.advance_time_and_run(.01) self.assertEventNotCalled("kickback_kickback_test_fired") # enable kickback self.post_event("kickback_enable") self.advance_time_and_run(.01) # should write a hw rule self.machine.default_platform.set_pulse_on_hit_rule.assert_called_once_with( SwitchSettings( hw_switch=self.machine.switches["s_kickback"].hw_switch, invert=False, debounce=False), DriverSettings( hw_driver=self.machine.coils["kickback_coil"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=100), hold_settings=None, recycle=True)) # a hit should fire it self.hit_and_release_switch("s_kickback") self.advance_time_and_run(.01) self.assertEventCalled("kickback_kickback_test_fired") # ball save should be enabled just in case self.assertTrue(self.machine.ball_saves["kickback_save"].enabled) # but disable after 6s self.advance_time_and_run(6.1) self.assertFalse(self.machine.ball_saves["kickback_save"].enabled) # it only works once though self.mock_event("kickback_kickback_test_fired") self.hit_and_release_switch("s_kickback") self.advance_time_and_run(.01) self.assertEventNotCalled("kickback_kickback_test_fired")
def test_coil_player_in_mode(self): coil = self.machine.coils['coil_3'] coil.hw_driver.enable = MagicMock() coil.hw_driver.disable = MagicMock() # start mode self.post_event("start_mode1", 1) self.assertFalse(coil.hw_driver.enable.called) self.assertFalse(coil.hw_driver.disable.called) # enable coil self.post_event("event1_mode", 1) coil.hw_driver.enable.assert_called_with(PulseSettings(power=1.0, duration=10), HoldSettings(power=1.0)) coil.hw_driver.enable = MagicMock() self.assertFalse(coil.hw_driver.disable.called) # on mode stop the coil player should disable the coil self.post_event("stop_mode1", 1) self.assertFalse(coil.hw_driver.enable.called) coil.hw_driver.disable.assert_called_with()
def _enable_now(self, pulse_ms: int = None, pulse_power: float = None, hold_power: float = None): self.info_log( "Enabling Driver with power %s (pulse_ms %sms and pulse_power %s)", hold_power, pulse_ms, pulse_power) self.hw_driver.enable( PulseSettings(power=pulse_power, duration=pulse_ms), HoldSettings(power=hold_power)) if self.config['max_hold_duration']: self.delay.add_if_doesnt_exist( self.config['max_hold_duration'] * 1000, self._enable_limit_reached, "enable_limit_reached") # inform bcp clients self.machine.bcp.interface.send_driver_event( action="enable", name=self.name, number=self.config['number'], pulse_ms=pulse_ms, pulse_power=pulse_power, hold_power=hold_power)
def testBasicFunctions(self): c_power = self.machine.coils["c_power"].hw_driver c_hold = self.machine.coils["c_hold"].hw_driver c_power.enable = MagicMock() c_power.disable = MagicMock() c_power.pulse = MagicMock() c_hold.enable = MagicMock() c_hold.disable = MagicMock() c_hold.pulse = MagicMock() # test enable self.machine.coils["c_test"].enable() c_power.pulse.assert_called_with(PulseSettings(power=1.0, duration=20)) c_power.pulse = MagicMock() assert not c_power.enable.called c_hold.enable.assert_called_with(PulseSettings(power=1.0, duration=10), HoldSettings(power=1.0)) c_hold.enable = MagicMock() assert not c_hold.pulse.called # test disable self.machine.coils["c_test"].disable() c_power.disable.assert_called_with() c_power.disable = MagicMock() c_hold.disable.assert_called_with() c_hold.disable = MagicMock() # test pulse self.machine.coils["c_test"].pulse(17) c_power.pulse.assert_called_with(PulseSettings(power=1.0, duration=17)) c_hold.pulse.assert_called_with(PulseSettings(power=1.0, duration=17)) # test default pulse self.machine.coils["c_test"].pulse() c_power.pulse.assert_called_with(PulseSettings(power=1.0, duration=20)) c_hold.pulse.assert_called_with(PulseSettings(power=1.0, duration=10))
def test_shows(self): # Make sure required modes have been loaded self.assertIn('mode1', self.machine.modes) self.assertIn('mode2', self.machine.modes) self.assertIn('mode3', self.machine.modes) # Make sure test shows exist and can be loaded self.assertIn('test_show1', self.machine.shows) self.assertIn('test_show2', self.machine.shows) self.assertIn('test_show3', self.machine.shows) # Make sure hardware devices have been configured for tests self.assertIn('led_01', self.machine.lights) self.assertIn('led_02', self.machine.lights) self.assertIn('light_01', self.machine.lights) self.assertIn('light_02', self.machine.lights) self.assertIn('gi_01', self.machine.lights) self.assertIn('coil_01', self.machine.coils) self.assertIn('flasher_01', self.machine.lights) # -------------------------------------------------------- # test_show1 - Show with LEDs, lights, and GI # -------------------------------------------------------- # LEDs should start out off (current color is default RGBColor object) self.assertLightColor("led_01", "off") self.assertLightColor("led_02", "off") # Lights should start out off (brightness is 0) self.assertLightChannel("light_01", 0) self.assertLightChannel("light_02", 0) # GI should start out disabled self.assertLightChannel("gi_01", 0) # Make sure all required shows are loaded start_time = time.time() while (not (self.machine.shows['test_show1'].loaded and self.machine.shows['test_show2'].loaded and self.machine.shows['test_show3'].loaded) and time.time() < start_time + 10): self.advance_time_and_run() self.assertTrue(self.machine.shows['test_show1'].loaded) self.assertEqual(self.machine.shows['test_show1'].total_steps, 5) # Start mode1 mode (should automatically start the test_show1 show) self.machine.events.post('start_mode1') self.advance_time_and_run(.2) self.assertTrue(self.machine.mode_controller.is_active('mode1')) self.assertTrue(self.machine.modes.mode1.active) self.assertIn(self.machine.modes.mode1, self.machine.mode_controller.active_modes) # Grab the running show instance running_show1 = self.machine.show_player.instances['mode1'][ 'show_player']['test_show1'] self.assertIsNotNone(running_show1) # Make sure the show is running at the proper priority (of the mode) self.assertEqual(running_show1.show_config.priority, 200) # Check LEDs, lights, and GI after first show step self.assertLightColor("led_01", '006400') self.assertEqual(200, self.machine.lights.led_01.stack[0].priority) self.assertLightColor("led_02", 'CCCCCC') self.assertEqual(200, self.machine.lights.led_02.stack[0].priority) self.assertLightChannel("light_01", 204) self.assertEqual(200, self.machine.lights.light_01.stack[0].priority) self.assertLightChannel("light_02", 120) self.assertEqual(200, self.machine.lights.light_02.stack[0].priority) self.assertLightChannel("gi_01", 255) # Check LEDs, lights, and GI after 2nd step self.advance_time_and_run() self.assertLightColor("led_01", 'DarkGreen') self.assertEqual(200, self.machine.lights.led_01.stack[0].priority) self.assertLightColor("led_02", 'Black') self.assertEqual(200, self.machine.lights.led_02.stack[0].priority) self.assertLightChannel("light_01", 204) self.assertEqual(200, self.machine.lights.light_01.stack[0].priority) self.assertLightChannel("light_02", 120) self.assertEqual(200, self.machine.lights.light_02.stack[0].priority) self.assertLightChannel("gi_01", 255) # Check LEDs, lights, and GI after 3rd step self.advance_time_and_run() self.assertLightColor("led_01", 'DarkSlateGray') self.assertEqual(200, self.machine.lights.led_01.stack[0].priority) self.assertLightColor("led_02", 'Tomato') self.assertEqual(200, self.machine.lights.led_02.stack[0].priority) self.assertLightChannel("light_01", 255) self.assertEqual(200, self.machine.lights.light_01.stack[0].priority) self.assertLightChannel("light_02", 51) self.assertEqual(200, self.machine.lights.light_02.stack[0].priority) self.assertLightChannel("gi_01", 153) # Check LEDs, lights, and GI after 4th step (includes a fade to next # color) self.advance_time_and_run() self.assertNotLightColor("led_01", 'MidnightBlue') self.assertEqual(200, self.machine.lights.led_01.stack[0].priority) self.assertNotLightColor("led_02", 'DarkOrange') self.assertEqual(200, self.machine.lights.led_02.stack[0].priority) self.assertLightChannel("light_01", 255) self.assertEqual(200, self.machine.lights.light_01.stack[0].priority) self.assertLightChannel("light_02", 51) self.assertEqual(200, self.machine.lights.light_02.stack[0].priority) self.assertLightChannel("gi_01", 51) # Advance time so fade should have completed self.advance_time_and_run(0.1) self.advance_time_and_run(0.1) self.advance_time_and_run(0.1) self.advance_time_and_run(0.1) self.advance_time_and_run(0.1) self.advance_time_and_run(0.1) self.assertLightColor("led_01", 'MidnightBlue') self.assertLightColor("led_02", 'DarkOrange') # Check LEDs after 5th step (includes a fade to black/off) self.advance_time_and_run(0.4) self.assertNotLightColor("led_01", 'Off') self.assertNotLightColor("led_02", 'Off') self.assertNotLightChannel("light_01", 0) self.assertNotLightChannel("light_02", 0) # Advance time so fade should have completed self.advance_time_and_run(0.2) self.advance_time_and_run(0.2) self.advance_time_and_run(0.2) self.advance_time_and_run(0.2) self.advance_time_and_run(0.2) self.assertLightColor("led_01", 'Off') self.assertLightColor("led_02", 'Off') self.assertLightChannel("light_01", 0) self.assertLightChannel("light_02", 0) self.assertLightChannel("gi_01", 0) # Make sure show loops back to the first step self.advance_time_and_run(1.1) self.assertLightColor("led_01", '006400') self.assertLightColor("led_02", 'CCCCCC') self.assertLightChannel("light_01", 204) self.assertLightChannel("light_02", 120) self.assertLightChannel("gi_01", 255) self.assertNotIn( "show_from_mode", self.machine.show_player.instances['mode1']['show_player']) self.machine.set_machine_var("test", 42) self.advance_time_and_run(.01) self.assertTrue(self.machine.show_player.instances['mode1'] ['show_player']['show_from_mode']) # Stop the mode (and therefore the show) self.machine.events.post('stop_mode1') self.machine_run() self.assertNotIn( "show_from_mode", self.machine.show_player.instances['mode1']['show_player']) self.assertFalse(self.machine.mode_controller.is_active('mode1')) self.assertTrue(running_show1._stopped) self.assertNotIn( "test_show1", self.machine.show_player.instances['mode1']['show_player']) self.advance_time_and_run(5) # Make sure the lights and LEDs have reverted back to their prior # states from before the show started self.assertLightColor("led_01", "off") self.assertFalse(self.machine.lights.led_01.stack) self.assertLightColor("led_01", "off") self.assertFalse(self.machine.lights.led_02.stack) self.assertLightChannel("light_01", 0) self.assertFalse(self.machine.lights.light_01.stack) self.assertLightChannel("light_02", 0) self.assertFalse(self.machine.lights.light_02.stack) self.assertLightChannel("gi_01", 0) # -------------------------------------------------------- # test_show2 - Show with events # -------------------------------------------------------- # Setup callback for test_event event (fired in test show) and triggers self.event_handler = MagicMock() self.event_handler_2 = MagicMock() self.machine.events.add_handler('test_event', self.event_handler) self.machine.events.add_handler('play_sound', self.event_handler_2) # Advance the clock enough to ensure the shows have time to load self.assertTrue(self.machine.shows['test_show2'].loaded) self.assertEqual(self.machine.shows['test_show2'].total_steps, 3) # Make sure our event callbacks have not been fired yet self.assertFalse(self.event_handler.called) self.assertFalse(self.event_handler_2.called) # Start the mode that will trigger playback of the test_show2 show self.machine.events.post('start_mode2') self.machine_run() self.assertTrue(self.machine.mode_controller.is_active('mode2')) self.assertTrue(self.machine.modes.mode2.active) self.assertIn(self.machine.modes.mode2, self.machine.mode_controller.active_modes) self.assertTrue(self.machine.show_player.instances['mode2'] ['show_player']['test_show2']) self.machine_run() # Make sure event callbacks have been called self.assertTrue(self.event_handler.called) self.assertTrue(self.event_handler_2.called) self.event_handler_2.assert_called_with(priority=0, sound="test_1", loops=-1, volume=0.5) # Advance to next show step and check for event self.advance_time_and_run() self.event_handler_2.assert_called_with(priority=0, sound="test_2") # Advance to next show step and check for event self.advance_time_and_run() self.event_handler_2.assert_called_with(priority=0, sound="test_3", loops=1, volume=0.35) # Stop the mode (and therefore the show) self.machine.events.post('stop_mode2') self.machine_run() self.assertFalse(self.machine.mode_controller.is_active('mode2')) self.advance_time_and_run(5) # -------------------------------------------------------- # test_show3 - Show with coils and flashers # -------------------------------------------------------- # Setup callback for test_event event (fired in test show) and triggers self.machine.coils['coil_01'].hw_driver.pulse = MagicMock() self.machine.coils['flasher_01'].hw_driver.enable = MagicMock() self.assertTrue(self.machine.shows['test_show3'].loaded) self.assertEqual(self.machine.shows['test_show3'].total_steps, 3) # Make sure our device callbacks have not been fired yet self.assertFalse(self.machine.coils['coil_01'].hw_driver.pulse.called) self.assertFalse( self.machine.coils['flasher_01'].hw_driver.enable.called) # Start the mode that will trigger playback of the test_show3 show self.machine.events.post('start_mode3') self.machine_run() self.assertTrue(self.machine.mode_controller.is_active('mode3')) self.assertTrue(self.machine.modes.mode3.active) self.assertIn(self.machine.modes.mode3, self.machine.mode_controller.active_modes) self.machine.show_player.instances['mode3']['show_player'][ 'test_show3'] self.machine_run() # Make sure flasher device callback has been called (in first step # of show) self.advance_time_and_run(.01) self.assertTrue( self.machine.coils['flasher_01'].hw_driver.enable.called) # Advance to next show step and check for coil firing self.advance_time_and_run() self.machine.coils['coil_01'].hw_driver.pulse.assert_called_with( PulseSettings(power=1.0, duration=30)) # Advance to next show step and check for coil firing self.advance_time_and_run() self.machine.coils['coil_01'].hw_driver.pulse.assert_called_with( PulseSettings(power=0.45, duration=30))
def test_hold_no_eos(self): self.machine.default_platform.set_pulse_on_hit_and_release_rule = MagicMock() self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock() # Config uses enable_events to enable the flipper on boot self.assertTrue(self.machine.flippers["left_flipper"]._enabled) self.machine.flippers["left_flipper"].disable() self.assertFalse(self.machine.flippers["left_flipper"]._enabled) self.machine.flippers["left_flipper"].enable() # def set_hw_rule(self, sw_name, sw_activity, driver_name, driver_action, # disable_on_release=True, drive_now=False, # **driver_settings_overrides): self.assertEqual(1, len(self.machine.default_platform.set_pulse_on_hit_and_release_rule._mock_call_args_list)) self.assertEqual(1, len(self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule. _mock_call_args_list)) self.machine.default_platform.set_pulse_on_hit_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=30), hold_settings=None, recycle=False) ) self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_hold"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=1.0), recycle=False) ) self.machine.default_platform.clear_hw_rule = MagicMock() self.machine.flippers["left_flipper"].disable() self.assertFalse(self.machine.flippers["left_flipper"]._enabled) self.machine.default_platform.clear_hw_rule.assert_has_calls( [call( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=30), hold_settings=None, recycle=False) ), call( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_hold"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=1.0), recycle=False) ) ], any_order=True) self.machine.default_platform.set_pulse_on_hit_and_release_rule = MagicMock() self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule = MagicMock() self.machine.flippers["left_flipper"].enable() self.machine.default_platform.set_pulse_on_hit_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_main"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=30), hold_settings=None, recycle=False) ) self.machine.default_platform.set_pulse_on_hit_and_enable_and_release_rule.assert_called_once_with( SwitchSettings(hw_switch=self.machine.switches["s_left_flipper"].hw_switch, invert=False, debounce=False), DriverSettings(hw_driver=self.machine.coils["c_flipper_left_hold"].hw_driver, pulse_settings=PulseSettings(power=1.0, duration=10), hold_settings=HoldSettings(power=1.0), recycle=False) )