コード例 #1
0
    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()
コード例 #2
0
    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))
コード例 #3
0
    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
コード例 #4
0
    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))
コード例 #5
0
ファイル: test_Flippers.py プロジェクト: unRARed/mpf
    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())
コード例 #6
0
    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()
コード例 #7
0
    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
コード例 #8
0
ファイル: driver.py プロジェクト: unRARed/mpf
 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)
コード例 #9
0
ファイル: opp.py プロジェクト: wszamotula/mpf
    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
コード例 #10
0
ファイル: opp_coil.py プロジェクト: mfulleratlassian/mpf
 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)
コード例 #11
0
 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)
コード例 #12
0
    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)
コード例 #13
0
    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
コード例 #14
0
    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)
コード例 #15
0
ファイル: digital_output.py プロジェクト: krayon/pinball-mpf
 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))
コード例 #16
0
 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))
コード例 #17
0
ファイル: digital_output.py プロジェクト: murrphy/mpf
 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))
コード例 #18
0
    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)
コード例 #19
0
ファイル: digital_output.py プロジェクト: krayon/pinball-mpf
 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))
コード例 #20
0
 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))
コード例 #21
0
    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)
コード例 #22
0
    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()
コード例 #23
0
    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)
コード例 #24
0
    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)
コード例 #25
0
    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")
コード例 #26
0
    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()
コード例 #27
0
ファイル: driver.py プロジェクト: krayon/pinball-mpf
    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)
コード例 #28
0
    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))
コード例 #29
0
    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))
コード例 #30
0
    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)
        )