Skip to content

Commit

Permalink
Added rgbw_white_behavior setting, v0.57.0.dev23
Browse files Browse the repository at this point in the history
  • Loading branch information
toomanybrians committed Oct 15, 2023
1 parent 465bafe commit 44ea3fc
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 13 deletions.
2 changes: 1 addition & 1 deletion mpf/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"""

__version__ = '0.57.0.dev22' # Also consider whether MPF-MC pyproject.toml should be updated
__version__ = '0.57.0.dev23' # Also consider whether MPF-MC pyproject.toml should be updated
'''The full version of MPF.'''

__short_version__ = '0.57'
Expand Down
1 change: 1 addition & 0 deletions mpf/config_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ mpf:
platforms: ignore
paths: ignore
report_crashes: single|enum(ask,never,always)|ask
rgbw_white_behavior: single|enum(white_only,min_rgb,duck_rgb)|duck_rgb
mpf-mc:
__valid_in__: machine # todo add to validator
__type__: config
Expand Down
42 changes: 33 additions & 9 deletions mpf/devices/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Light(SystemWideDevice, DevicePositionMixin):
class_label = 'light'

__slots__ = ["hw_drivers", "platforms", "delay", "default_fade_ms", "_color_correction_profile", "stack",
"_off_color", "_drivers_loaded", "_last_fade_target", "_is_rgbw"]
"_off_color", "_drivers_loaded", "_last_fade_target", "_rbgw_style"]

def __init__(self, machine, name):
"""initialize light."""
Expand All @@ -73,7 +73,7 @@ def __init__(self, machine, name):

self._color_correction_profile = None
self._last_fade_target = None
self._is_rgbw = False
self._rbgw_style = None # RGBW LED will be white_only, min_rgb, duck_rgb. Others are None

self.stack = list() # type: List[LightStackEntry]
"""A list of dicts which represents different commands that have come
Expand Down Expand Up @@ -344,7 +344,7 @@ async def _initialize(self):
['default_fade_ms'])

if len(self.hw_drivers) == 4 and all(channel in self.hw_drivers for channel in ['red', 'green', 'blue', 'white']):
self._is_rgbw = True
self._rbgw_style = self.machine.config['mpf']['rgbw_white_behavior']

self.debug_log("Initializing Light. CC Profile: %s, "
"Default fade: %sms", self._color_correction_profile,
Expand Down Expand Up @@ -616,21 +616,45 @@ def _schedule_update(self):

for color, drivers in self.hw_drivers.items():
if color in ["red", "blue", "green"]:
if self._is_rgbw: # Remove the white channel from the RGB channels
if self._rbgw_style == "duck_rgb":
start_brightness = (getattr(start_color, color) -
min(start_color.red, start_color.green, start_color.blue)) / 255.0
target_brightness = (getattr(target_color, color) -
min(target_color.red, target_color.green, target_color.blue)) / 255.0
else:
elif self._rbgw_style == "white_only": # any shade of white is moved to the white channel
if start_color.red == start_color.green == start_color.blue:
start_brightness = 0.0
else:
start_brightness = getattr(start_color, color) / 255.0
if target_color.red == target_color.green == target_color.blue:
target_brightness = 0.0
else:
target_brightness = getattr(target_color, color) / 255.0
else: # min_rgb or None (non-RGBW)
start_brightness = getattr(start_color, color) / 255.0
target_brightness = getattr(target_color, color) / 255.0
elif color == "white": # This works to convert RGB to white and figure out the W for RGBW from RGB
start_brightness = min(start_color.red, start_color.green, start_color.blue) / 255.0
target_brightness = min(target_color.red, target_color.green, target_color.blue) / 255.0

elif color == "white":
if self._rbgw_style == "white_only":
if start_color.red == start_color.green == start_color.blue:
start_brightness = start_color.red / 255.0
else:
start_brightness = 0.0
if target_color.red == target_color.green == target_color.blue:
target_brightness = target_color.red / 255.0
else:
target_brightness = 0.0
else: # white is the minimum of RGB
start_brightness = min(start_color.red, start_color.green, start_color.blue) / 255.0
target_brightness = min(target_color.red, target_color.green, target_color.blue) / 255.0
else:
raise ColorException("Invalid color {}".format(color))

for driver in drivers:
driver.set_fade(start_brightness, start_time, target_brightness, target_time)
try:
driver.set_fade(start_brightness, start_time, target_brightness, target_time)
except UnboundLocalError:
print()

for platform in self.platforms:
platform.light_sync()
Expand Down
45 changes: 42 additions & 3 deletions mpf/tests/test_DeviceLight.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def test_non_rgb_leds(self):
self.assertEqual('led-4', led.hw_drivers["red"][0].number)

led = self.machine.lights["led_bgr_2"]
self.assertFalse(led._is_rgbw)
self.assertFalse(led._rbgw_style)
led.color(RGBColor((11, 23, 42)))
self.advance_time_and_run(1)
self.assertEqual(42 / 255.0, led.hw_drivers["blue"][0].current_brightness)
Expand All @@ -397,7 +397,7 @@ def test_non_rgb_leds(self):

# test rgbw via manual channel entries
led = self.machine.lights["led3"]
self.assertTrue(led._is_rgbw)
self.assertEqual(led._rbgw_style, "duck_rgb")
led.color(RGBColor((11, 23, 42)))
self.advance_time_and_run(1)
self.assertEqual(0 / 255.0, led.hw_drivers["red"][0].current_brightness)
Expand All @@ -413,8 +413,47 @@ def test_non_rgb_leds(self):
self.assertEqual(0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(1, led.hw_drivers["white"][0].current_brightness)

# test min_rgbw
led._rbgw_style = "min_rgbw"
led.color(RGBColor((11, 23, 42)))
self.advance_time_and_run(1)
self.assertEqual(11 / 255.0, led.hw_drivers["red"][0].current_brightness)
self.assertEqual(23 / 255.0, led.hw_drivers["green"][0].current_brightness)
self.assertEqual(42 / 255.0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(11 / 255.0, led.hw_drivers["white"][0].current_brightness)

led.color(RGBColor((255, 255, 255)))
self.advance_time_and_run(1)
self.assertEqual(1.0, led.hw_drivers["red"][0].current_brightness)
self.assertEqual(1.0, led.hw_drivers["green"][0].current_brightness)
self.assertEqual(1.0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(1.0, led.hw_drivers["white"][0].current_brightness)

# test rgbw white only
led._rbgw_style = "white_only"
led.color(RGBColor((11, 23, 42)))
self.advance_time_and_run(1)
self.assertEqual(11 / 255.0, led.hw_drivers["red"][0].current_brightness)
self.assertEqual(23 / 255.0, led.hw_drivers["green"][0].current_brightness)
self.assertEqual(42 / 255.0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(0 / 255.0, led.hw_drivers["white"][0].current_brightness)

led.color(RGBColor((255, 255, 255)))
self.advance_time_and_run(1)
self.assertEqual(0.0, led.hw_drivers["red"][0].current_brightness)
self.assertEqual(0.0, led.hw_drivers["green"][0].current_brightness)
self.assertEqual(0.0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(1.0, led.hw_drivers["white"][0].current_brightness)

led.color(RGBColor((100, 100, 100)))
self.advance_time_and_run(1)
self.assertEqual(0.0, led.hw_drivers["red"][0].current_brightness)
self.assertEqual(0.0, led.hw_drivers["green"][0].current_brightness)
self.assertEqual(0.0, led.hw_drivers["blue"][0].current_brightness)
self.assertEqual(100 / 255.0, led.hw_drivers["white"][0].current_brightness)

# type type: rgbw
self.assertTrue(self.machine.lights["led5"]._is_rgbw)
self.assertEqual(self.machine.lights["led5"]._rbgw_style, "duck_rgb")

# test www light
led = self.machine.lights["led_www"]
Expand Down

0 comments on commit 44ea3fc

Please sign in to comment.